def execute_image_operations(self): self.context.request.quality = None req = self.context.request conf = self.context.config req.extension = splitext(req.image_url)[-1].lower() should_store = self.context.config.RESULT_STORAGE_STORES_UNSAFE or not self.context.request.unsafe if self.context.modules.result_storage and should_store: start = datetime.datetime.now() result = self.context.modules.result_storage.get() finish = datetime.datetime.now() self.context.statsd_client.timing('result_storage.incoming_time', total_seconds_of(finish - start) * 1000) if result is None: self.context.statsd_client.incr('result_storage.miss') else: self.context.statsd_client.incr('result_storage.hit') self.context.statsd_client.incr('result_storage.bytes_read', len(result)) if result is not None: mime = BaseEngine.get_mimetype(result) if mime == '.gif' and self.context.config.USE_GIFSICLE_ENGINE: self.context.request.engine = GifEngine(self.context) self.context.request.engine.load(result, '.gif') else: self.context.request.engine = self.context.modules.engine logger.debug('[RESULT_STORAGE] IMAGE FOUND: %s' % req.url) self.finish_request(self.context, result) return if conf.MAX_WIDTH and (not isinstance(req.width, basestring)) and req.width > conf.MAX_WIDTH: req.width = conf.MAX_WIDTH if conf.MAX_HEIGHT and (not isinstance(req.height, basestring)) and req.height > conf.MAX_HEIGHT: req.height = conf.MAX_HEIGHT req.meta_callback = conf.META_CALLBACK_NAME or self.request.arguments.get('callback', [None])[0] self.filters_runner = self.context.filters_factory.create_instances(self.context, self.context.request.filters) self.filters_runner.apply_filters(thumbor.filters.PHASE_PRE_LOAD, self.get_image)
def finish_request(self, context, result=None): image_extension, content_type = self.define_image_type(context, result) quality = self.context.request.quality if quality is None: if image_extension == '.webp': quality = self.context.config.get('WEBP_QUALITY', self.context.config.QUALITY) else: quality = self.context.config.QUALITY self.set_header('Server', 'Thumbor/%s' % __version__) if context.config.AUTO_WEBP and not context.request.engine.is_multiple() and context.request.engine.extension != '.webp': self.set_header('Vary', 'Accept') max_age = self.context.config.MAX_AGE if self.context.request.max_age is not None: max_age = self.context.request.max_age if context.request.prevent_result_storage or context.request.detection_error: max_age = self.context.config.MAX_AGE_TEMP_IMAGE if max_age: self.set_header('Cache-Control', 'max-age=' + str(max_age) + ',public') self.set_header('Expires', datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age)) # needs to be decided before loading results from the engine should_store = result is None and (context.config.RESULT_STORAGE_STORES_UNSAFE or not context.request.unsafe) if result is None: results = context.request.engine.read(image_extension, quality) if context.request.max_bytes is not None: results = self.reload_to_fit_in_kb( context.request.engine, results, image_extension, quality, context.request.max_bytes ) if not context.request.meta: results = self.optimize(context, image_extension, results) else: if self.context.config.SEND_IF_MODIFIED_LAST_MODIFIED_HEADERS: # Handle If-Modified-Since & Last-Modified header try: result_last_modified = self.context.modules.result_storage.last_updated() except NotImplementedError: logger.warn('last_updated method is not supported by your result storage service, hence If-Modified-Since & Last-Updated headers support is disabled.') if result_last_modified: if 'If-Modified-Since' in self.request.headers: date_modified_since = datetime.datetime.strptime(self.request.headers['If-Modified-Since'], HTTP_DATE_FMT) if result_last_modified <= date_modified_since: self.set_status(304) self.finish() return self.set_header('Last-Modified', result_last_modified.strftime(HTTP_DATE_FMT)) results = result if context.request.format and ('mp4' in context.request.format or 'webm' in context.request.format): self.set_header('Content-Type', 'video/%s' % context.request.format) else: self.set_header('Content-Type', content_type) self.write(results) self.finish() if should_store: if context.modules.result_storage and not context.request.prevent_result_storage: start = datetime.datetime.now() context.modules.result_storage.put(results) finish = datetime.datetime.now() context.statsd_client.incr('result_storage.bytes_written', len(results)) context.statsd_client.timing('result_storage.outgoing_time', total_seconds_of(finish - start) * 1000)