Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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)