def __init__(self, context): self.context = context handlers = [ (r'/healthcheck', HealthcheckHandler), ] if context.config.UPLOAD_ENABLED: # TODO Old handler to upload images handlers.append( (r'/upload', UploadHandler, {'context': self.context}) ) # Handler to upload images (POST). handlers.append( (r'/image', ImagesHandler, {'context': self.context}) ) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append( (r'/image/(.*)', ImageHandler, {'context': self.context}) ) # Imaging handler (GET) handlers.append( (Url.regex(), ImagingHandler, {'context': self.context}) ) super(ThumborServiceApp, self).__init__(handlers)
def get_handlers(self): handlers = [ (r'/healthcheck', HealthcheckHandler), ] if self.context.config.UPLOAD_ENABLED: # TODO Old handler to upload images handlers.append((r'/upload', UploadHandler, { 'context': self.context })) # Handler to upload images (POST). handlers.append((r'/image', ImagesHandler, { 'context': self.context })) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append((r'/image/(.*)', ImageHandler, { 'context': self.context })) # Imaging handler (GET) handlers.append((Url.regex(), ImagingHandler, { 'context': self.context })) return handlers
def test_returns_route_regex_with_filters(): class TestFilter(object): regex = r'some-filter-fake-regex' url = Url.regex(filters=[TestFilter]) assert url == '/?unsafe/(?:(?P<meta>meta)/)?(?:(?P<crop_left>\d+)x(?P<crop_top>\d+):(?P<crop_right>\d+)x(?P<crop_bottom>\d+)/)?(?:(?P<fit_in>fit-in)/)?(?:(?P<horizontal_flip>-)?(?P<width>\d+)?x(?P<vertical_flip>-)?(?P<height>\d+)?/)?(?:(?P<halign>left|right|center)/)?(?:(?P<valign>top|bottom|middle)/)?(?:(?P<smart>smart)/)?some-filter-fake-regex(?P<image>.+)'
def post(self, **kw): paths = self.get_arguments('paths[]') if len(paths) > MultiHandler.paths_limit: self.set_status(400) super(MultiHandler, self).write('Too many paths: %d max' % MultiHandler.paths_limit) super(MultiHandler, self).finish() return for path in paths: request = HTTPServerRequest(method='GET', uri=path, host=self.request.host, connection=self.request.connection) handler = MultiHandler(self.application, request, context=self.context) # Copy over the storage as-is, which allows those requests to # share storage if needed (useful for request-storage) handler.context.modules.storage = self.context.modules.storage m = re.match(Url.regex(), path) yield handler.check_image(m.groupdict()) # Close the request ASAP, the work is to be done async self.set_status(200) super(MultiHandler, self).finish()
def get_handlers(self): # Imaging handler (GET) return [(BuzzFeedHandler.regex(), BuzzFeedHandler, { 'context': self.context }), (Url.regex(), ImagingHandler, { 'context': self.context })]
def path_to_parameters(cls, path): ''' :param path: url path :return: A dictionary of parameters to be used with ImagingHandler instances ''' if not cls._url_regex: cls._url_regex = re.compile(Url.regex()) if cls._url_regex.groups: match = cls._url_regex.match(path) # Pass matched groups to the handler. Since # match.groups() includes both named and # unnamed groups, we want to use either groups # or groupdict but not both. if cls._url_regex.groupindex: parameters = dict((str(k), tornado.web._unquote_or_none(v)) for (k, v) in match.groupdict().items()) else: parameters = [ tornado.web._unquote_or_none(s) for s in match.groups() ] else: parameters = dict() return parameters
def path_to_parameters(cls, path): ''' :param path: url path :return: A dictionary of parameters to be used with ImagingHandler instances ''' if not cls._url_regex: cls._url_regex = re.compile(Url.regex()) if cls._url_regex.groups: match = cls._url_regex.match(path) # See https://github.com/tornadoweb/tornado/blob/01c78ebfcc993ff4f1d8336c2c45844fe9dab60e/tornado/web.py#L1951 # Pass matched groups to the handler. Since # match.groups() includes both named and # unnamed groups, we want to use either groups # or groupdict but not both. if cls._url_regex.groupindex: parameters = dict( (str(k), tornado.web._unquote_or_none(v)) for (k, v) in match.groupdict().items()) else: parameters = [ tornado.web._unquote_or_none(s) for s in match.groups() ] else: parameters = dict() return parameters
def get_handlers(self): handlers = [ (r'/healthcheck', HealthcheckHandler), ] if self.context.config.UPLOAD_ENABLED: # Handler to upload images (POST). handlers.append( (r'/image', ImageUploadHandler, {'context': self.context}) ) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append( (r'/image/(.*)', ImageResourceHandler, {'context': self.context}) ) if self.context.config.USE_BLACKLIST: handlers.append( (r'/blacklist', BlacklistHandler, {'context': self.context}) ) # Imaging handler (GET) handlers.append( (Url.regex(), ImagingHandler, {'context': self.context}) ) return handlers
def get_handlers(self): handlers = [ (r'/healthcheck', HealthcheckHandler), ] if self.context.config.UPLOAD_ENABLED: # TODO: Old handler to upload images. Will be deprecated soon. handlers.append( (r'/upload', LegacyImageUploadHandler, {'context': self.context}) ) # Handler to upload images (POST). handlers.append( (r'/image', ImageUploadHandler, {'context': self.context}) ) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append( (r'/image/(.*)', ImageResourceHandler, {'context': self.context}) ) if self.context.config.USE_BLACKLIST: handlers.append( (r'/blacklist', BlacklistHandler, {'context': self.context}) ) # Imaging handler (GET) handlers.append( (Url.regex(not self.context.config.SECURITY_DISABLE_KEY), ImagingHandler, {'context': self.context}) ) return handlers
def post(self, **kw): paths = self.get_arguments('paths[]') if len(paths) > MultiHandler.paths_limit: self.set_status(400) super(MultiHandler, self).write( 'Too many paths: %d max' % MultiHandler.paths_limit ) super(MultiHandler, self).finish() return for path in paths: request = HTTPServerRequest( method='GET', uri=path, host=self.request.host, connection=self.request.connection ) handler = MultiHandler( self.application, request, context=self.context ) # Copy over the storage as-is, which allows those requests to # share storage if needed (useful for request-storage) handler.context.modules.storage = self.context.modules.storage m = re.match(Url.regex(), path) yield handler.check_image(m.groupdict()) # Close the request ASAP, the work is to be done async self.set_status(200) super(MultiHandler, self).finish()
def get_handlers(self): handlers = [ (self.context.config.HEALTHCHECK_ROUTE, HealthcheckHandler), ] if self.context.config.UPLOAD_ENABLED: # Handler to upload images (POST). handlers.append((r'/image', ImageUploadHandler, { 'context': self.context })) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append((r'/image/(.*)', ImageResourceHandler, { 'context': self.context })) if self.context.config.USE_BLACKLIST: handlers.append((r'/blacklist', BlacklistHandler, { 'context': self.context })) # Imaging handler (GET) handlers.append((Url.regex(), ImagingHandler, { 'context': self.context })) return handlers
def get_handlers(self): handlers = [ (r'/', HealthcheckHandler), (r'/favicon.ico', FaviconHandler), ] if self.context.config.UPLOAD_ENABLED: # TODO: Old handler to upload images. Will be deprecated soon. handlers.append( (r'/upload', LegacyImageUploadHandler, {'context': self.context}) ) # Handler to upload images (POST). handlers.append( (r'/image', ImageUploadHandler, {'context': self.context}) ) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append( (r'/image/(.*)', ImageResourceHandler, {'context': self.context}) ) if self.context.config.USE_BLACKLIST: handlers.append( (r'/blacklist', BlacklistHandler, {'context': self.context}) ) # Imaging handler (GET) handlers.append( (Url.regex(), ImagingHandlerMine, {'context': self.context}) ) return handlers
def get_handlers(self): handlers = ThumborServiceApp.get_handlers(self) # Remove the default image handler handlers.pop() # Then install our own image handler handlers.append((Url.regex(), RewriteHandler, { 'context': self.context })) return handlers
def test_can_get_handlers(self): ctx = mock.Mock(config=mock.Mock( UPLOAD_ENABLED=False, USE_BLACKLIST=False, )) app = ThumborServiceApp(ctx) handlers = app.get_handlers() expect(handlers).to_length(2) expect(handlers[0][0]).to_equal(r'/healthcheck') expect(handlers[1][0]).to_equal(Url.regex())
def __init__(self, context): self.context = context handlers = [(r"/healthcheck", HealthcheckHandler)] if context.config.ENABLE_ORIGINAL_PHOTO_UPLOAD: handlers.append((r"/upload", UploadHandler, {"context": context})) handlers.append((Url.regex(), ImageProcessHandler, {"context": context})) super(ThumborServiceApp, self).__init__(handlers)
def test_can_get_regex_without_unsafe(self): regex = Url.regex(False) expect(regex).to_equal( '/?(?:(?P<debug>debug)/)?(?:(?P<meta>meta)/)?' '(?:(?P<trim>trim(?::(?:top-left|bottom-right))?(?::\\d+)?)/)?' '(?:(?P<crop_left>\\d+)x(?P<crop_top>\\d+):(?P<crop_right>\\d+)x(?P<crop_bottom>\\d+)/)?' '(?:(?P<adaptive>adaptive-)?(?P<full>full-)?(?P<fit_in>fit-in)/)?(?:(?P<horizontal_flip>-)?' '(?P<width>(?:\\d+|orig))?x(?P<vertical_flip>-)?(?P<height>(?:\\d+|orig))?/)?' '(?:(?P<halign>left|right|center)/)?(?:(?P<valign>top|bottom|middle)/)?' '(?:(?P<smart>smart)/)?(?:filters:(?P<filters>.+?\\))/)?(?P<image>.+)' )
def __init__(self, context): self.context = context handlers = [ (r'/healthcheck', HealthcheckHandler), ] if context.config.UPLOAD_ENABLED: handlers.append( (r'/upload', UploadHandler, { 'context': context }) ) handlers.append( (Url.regex(has_unsafe_or_hash=False,with_save=True), SaveHandler, { 'context': context }) ) handlers.append( (Url.regex(), ImageProcessHandler, { 'context': context }) ) super(ThumborServiceApp, self).__init__(handlers)
def test_can_get_handlers(self): ctx = mock.Mock( config=mock.Mock( UPLOAD_ENABLED=False, USE_BLACKLIST=False, ) ) app = ThumborServiceApp(ctx) handlers = app.get_handlers() expect(handlers).to_length(2) expect(handlers[0][0]).to_equal(r'/healthcheck') expect(handlers[1][0]).to_equal(Url.regex())
def __init__(self, conf_file=None, security_key=None, custom_handlers=None): if conf_file is None: conf_file = ThumborServiceApp.get_conf_file(conf_file) logger.info('Config file: %s' % conf_file) parse_config_file(conf_file) self.loader = real_import(conf.LOADER) self.storage = real_import(conf.STORAGE) self.engine = real_import(conf.ENGINE) self.detectors = [real_import(detector_name).Detector for detector_name in conf.DETECTORS] self.filters = [real_import(filter_name).Filter for filter_name in conf.FILTERS] filters.compile_filters(self.filters) # run again to overwrite the default settings on the # imported modules with the ones defined into the config file parse_config_file(conf_file) #storage = storage.Storage() #self.engine = self.engine.Engine() if security_key: options.SECURITY_KEY = security_key handler_context = { 'loader': self.loader, 'storage': self.storage, 'engine': self.engine, 'detectors': self.detectors, 'filters': self.filters } handlers = [ (r'/healthcheck', HealthcheckHandler) ] if conf.ALLOW_UNSAFE_URL: handlers.append( (Url.regex(), MainHandler, handler_context), ) if custom_handlers: for handler in custom_handlers: handlers.append((handler[0], handler[1], handler_context)) else: handlers.append( (r'/(?P<crypto>[^/]+)/(?P<image>(.+))', CryptoHandler, handler_context) ) super(ThumborServiceApp, self).__init__(handlers)
class Filter(BaseFilter): phase = PHASE_PRE_LOAD domain_regex = re.compile(r'^(https?://)?.*?/') url_regex = re.compile(Url.regex()) def parse_url(self, url): level = 0 while level < MAX_LEVEL: url = self.domain_regex.sub('', url) result = self.url_regex.match(url) if not result: return None parts = result.groupdict() image = parts.get('image', None) if not (image and (parts.get('hash', None) or parts.get('unsafe', None))): return None top, right, left, bottom = parts.get('crop_top', None), parts.get( 'crop_right', None), parts.get('crop_left', None), parts.get('crop_bottom', None) if top and right and left and bottom: return (image, top, right, left, bottom) url = image level += 1 return None @filter_method() def extract_focal(self): parts = self.parse_url(self.context.request.image_url) if parts: image, top, right, left, bottom = parts top, right, left, bottom = int(top), int(right), int(left), int( bottom) width = right - left height = bottom - top self.context.request.focal_points.append( FocalPoint.from_square(left, top, width, height, origin="Original Extraction")) self.context.request.image_url = image
def __init__(self, context): self.context = context handlers = [(r'/healthcheck', HealthcheckHandler)] if context.config.ALLOW_UNSAFE_URL: handlers.append((Url.regex(), MainHandler, {'context': context}), ) handlers.append( (r'/(?P<crypto>[^/]+)/(?P<image>(?:.+))', CryptoHandler, { 'context': context })) super(ThumborServiceApp, self).__init__(handlers)
def __init__(self, context): self.context = context handlers = [ (r'/healthcheck', HealthcheckHandler), ] if context.config.UPLOAD_ENABLED: handlers.append((r'/upload', UploadHandler, {'context': context})) handlers.append((Url.regex(), ImageProcessHandler, { 'context': context })) super(ThumborServiceApp, self).__init__(handlers)
def get(self, url): url = url.encode('utf-8') image = "" if self.context.config.get('SHORTENER_GENERATOR_PRESERVE_NAME'): reg = re.compile(Url.regex()) result = reg.match(url) if result is None: raise ValueError("URL does not match thumbor's URL pattern") result = result.groupdict() image = "/{image}".format(image=os.path.basename(result['image'])) return "{hash}{image}".format(hash=self.shorten(url), image=image)
def __init__(self, conf_file=None, custom_handlers=None): if conf_file is None: conf_file = ThumborServiceApp.get_conf_file(conf_file) logger.info('Config file: %s' % conf_file) parse_config_file(conf_file) loader = real_import(options.LOADER) storage = real_import(options.STORAGE) engine = real_import(options.ENGINE) detectors = [ real_import(detector_name).Detector for detector_name in options.DETECTORS ] filters = [ real_import(filter_name).Filter for filter_name in options.FILTERS ] # run again to overwrite the default settings on the # imported modules with the ones defined into the config file parse_config_file(conf_file) storage = storage.Storage() engine = engine.Engine() handler_context = { 'loader': loader, 'storage': storage, 'engine': engine, 'detectors': detectors, 'filters': filters } handlers = [(r'/healthcheck', HealthcheckHandler)] if options.ALLOW_UNSAFE_URL: handlers.append((Url.regex(), MainHandler, handler_context), ) if custom_handlers: for handler in custom_handlers: handlers.append((handler[0], handler[1], handler_context)) else: handlers.append((r'/(?P<crypto>[^/]+)/(?P<image>(.+))', EncryptedHandler, handler_context)) super(ThumborServiceApp, self).__init__(handlers)
def __init__(self, context): self.context = context handlers = [ (r'/healthcheck', HealthcheckHandler) ] if context.config.ALLOW_UNSAFE_URL: handlers.append( (Url.regex(), MainHandler, { 'context': context }), ) handlers.append( (r'/(?P<crypto>[^/]+)/(?P<image>(?:.+))', CryptoHandler, { 'context': context }) ) super(ThumborServiceApp, self).__init__(handlers)
def get_handlers(self): handlers = [(r"/healthcheck", HealthcheckHandler)] if self.context.config.UPLOAD_ENABLED: # TODO Old handler to upload images handlers.append((r"/upload", UploadHandler, {"context": self.context})) # Handler to upload images (POST). handlers.append((r"/image", ImagesHandler, {"context": self.context})) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append((r"/image/(.*)", ImageHandler, {"context": self.context})) # Imaging handler (GET) handlers.append((Url.regex(), ImagingHandler, {"context": self.context})) return handlers
def __init__(self, conf_file=None): if conf_file is None: conf_file = ThumborServiceApp.get_conf_file(conf_file) logger.info('Config file: %s' % conf_file) parse_config_file(conf_file) loader = real_import(options.LOADER) storage = real_import(options.STORAGE) engine = real_import(options.ENGINE) detectors = [] for detector_name in options.DETECTORS: detectors.append(real_import(detector_name).Detector) # run again to overwrite the default settings on the # imported modules with the ones defined into the config file parse_config_file(conf_file) storage = storage.Storage() engine = engine.Engine() handler_context = { 'loader': loader, 'storage': storage, 'engine': engine, 'detectors': detectors } handlers = [ (r'/healthcheck', HealthcheckHandler) ] if options.ALLOW_UNSAFE_URL: handlers.append( (Url.regex(), MainHandler, handler_context), ) handlers.append( (r'/(?P<crypto>[^/]+)/(?P<image>(.+))', EncryptedHandler, handler_context) ) super(ThumborServiceApp, self).__init__(handlers)
def get(self, url): url = url.encode('utf-8') image = "" if self.context.config.get('SHORTENER_GENERATOR_PRESERVE_NAME'): reg = re.compile(Url.regex()) result = reg.match(url) if result is None: raise ValueError("URL does not match thumbor's URL pattern") result = result.groupdict() image = "/{image}".format(image=os.path.basename(result['image'])) return "{hash}{image}".format( hash=self.shorten(url), image=image )
def get_handlers(self): handlers = [(r"/healthcheck", HealthcheckHandler)] if self.context.config.UPLOAD_ENABLED: # TODO: Old handler to upload images. Will be deprecated soon. handlers.append((r"/upload", LegacyImageUploadHandler, {"context": self.context})) # Handler to upload images (POST). handlers.append((r"/image", ImageUploadHandler, {"context": self.context})) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append((r"/image/(.*)", ImageResourceHandler, {"context": self.context})) if self.context.config.USE_BLACKLIST: handlers.append((r"/blacklist", BlacklistHandler, {"context": self.context})) # Imaging handler (GET) handlers.append((Url.regex(), ImagingHandler, {"context": self.context})) return handlers
def __init__(self, context): self.context = context handlers = [ (r'/healthcheck', HealthcheckHandler), ] # TODO Old handler to upload images if context.config.UPLOAD_ENABLED: handlers.append((r'/upload', UploadHandler, {'context': context})) # Handler to upload images (POST). handlers.append((r'/image', ImagesHandler, {'context': context})) # Handler to retrieve or modify existing images (GET, PUT, DELETE) handlers.append((r'/image/(.*)', ImageHandler, {'context': context})) # Imaging handler (GET) handlers.append((Url.regex(), ImagingHandler, {'context': context})) super(ThumborServiceApp, self).__init__(handlers)
def path_to_parameters(cls, path): """ :param path: url path :return: A dictionary of parameters to be used with ImagingHandler instances """ if not cls._url_regex: cls._url_regex = re.compile(Url.regex()) if cls._url_regex.groups: match = cls._url_regex.match(path) # Pass matched groups to the handler. Since # match.groups() includes both named and # unnamed groups, we want to use either groups # or groupdict but not both. if cls._url_regex.groupindex: parameters = dict((str(k), tornado.web._unquote_or_none(v)) for (k, v) in match.groupdict().items()) else: parameters = [tornado.web._unquote_or_none(s) for s in match.groups()] else: parameters = dict() return parameters
def test_returns_route_regex_without_image(): url = Url.regex(include_image=False) assert url == '/?unsafe/(?:(?P<meta>meta)/)?(?:(?P<crop_left>\d+)x(?P<crop_top>\d+):(?P<crop_right>\d+)x(?P<crop_bottom>\d+)/)?(?:(?P<horizontal_flip>-)?(?P<width>\d+)?x(?P<vertical_flip>-)?(?P<height>\d+)?/)?(?:(?P<halign>left|right|center)/)?(?:(?P<valign>top|bottom|middle)/)?(?:(?P<smart>smart)/)?'
def topic(self): return Url.regex(old_format=True)
def topic(self): return Url.regex()
def test_returns_route_regex_without_image(): url = Url.regex(include_image=False) assert url == '/?unsafe/(?:(?P<meta>meta)/)?(?:(?P<crop_left>\d+)x(?P<crop_top>\d+):(?P<crop_right>\d+)x(?P<crop_bottom>\d+)/)?(?:(?P<fit_in>fit-in)/)?(?:(?P<horizontal_flip>-)?(?P<width>\d+)?x(?P<vertical_flip>-)?(?P<height>\d+)?/)?(?:(?P<halign>left|right|center)/)?(?:(?P<valign>top|bottom|middle)/)?(?:(?P<smart>smart)/)?'
def test_returns_route_regex_with_default_filters(): url = Url.regex() assert url == '/?unsafe/(?:(?P<meta>meta)/)?(?:(?P<crop_left>\d+)x(?P<crop_top>\d+):(?P<crop_right>\d+)x(?P<crop_bottom>\d+)/)?(?:(?P<fit_in>fit-in)/)?(?:(?P<horizontal_flip>-)?(?P<width>\d+)?x(?P<vertical_flip>-)?(?P<height>\d+)?/)?(?:(?P<halign>left|right|center)/)?(?:(?P<valign>top|bottom|middle)/)?(?:(?P<smart>smart)/)?(?P<image>.+)'
def topic(self): return Url.regex(include_image=False)
def get_handlers(self): handlers = super(App, self).get_handlers() handlers.insert(0, (Url.regex(), Handler, {'context': self.context})) return handlers