Ejemplo n.º 1
0
    def _factory(options):
        multipart_handler = media.MultipartFormHandler()
        for key, value in options.items():
            setattr(multipart_handler.parse_options, key, value)
        req_handlers = media.Handlers({
            falcon.MEDIA_JSON:
            media.JSONHandler(),
            falcon.MEDIA_MULTIPART:
            multipart_handler,
        })

        app = create_app(asgi)
        app.req_options.media_handlers = req_handlers
        app.resp_options.media_handlers = media.Handlers({
            falcon.MEDIA_JSON:
            media.JSONHandler(),
            falcon.MEDIA_MSGPACK:
            media.MessagePackHandler(),
        })

        resource = AsyncMultipartAnalyzer() if asgi else MultipartAnalyzer()
        app.add_route('/submit', resource)
        app.add_route('/media', resource, suffix='media')
        app.add_route('/mirror', resource, suffix='mirror')

        return testing.TestClient(app)
Ejemplo n.º 2
0
def test_sync_methods_not_overridden(asgi):
    app = create_app(asgi)

    class FaultyHandler(media.BaseHandler):
        pass

    handlers = media.Handlers({'application/json': FaultyHandler()})
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            resp.media = {}

        def on_post(self, req, resp):
            req.media

    class ResourceAsync:
        async def on_get(self, req, resp):
            resp.media = {}

        async def on_post(self, req, resp):
            await req.get_media()

    app.add_route('/', ResourceAsync() if asgi else Resource())

    # NOTE(caselit): force serialization in xml, since error.to_json uses the faulty handler
    result = testing.simulate_get(app, '/', headers={'Accept': 'text/xml'})
    assert result.status_code == 500

    result = testing.simulate_post(app, '/', json={}, headers={'Accept': 'text/xml'})
    assert result.status_code == 500
Ejemplo n.º 3
0
def test_sync_methods_not_overridden(asgi):
    app = create_app(asgi)

    class FaultyHandler(media.BaseHandler):
        pass

    handlers = media.Handlers({'application/json': FaultyHandler()})
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            resp.media = {}

        def on_post(self, req, resp):
            req.media

    class ResourceAsync:
        async def on_get(self, req, resp):
            resp.media = {}

        async def on_post(self, req, resp):
            await req.get_media()

    app.add_route('/', ResourceAsync() if asgi else Resource())

    result = testing.simulate_get(app, '/')
    assert result.status_code == 500

    result = testing.simulate_post(app, '/', json={})
    assert result.status_code == 500
Ejemplo n.º 4
0
def get_app():
    app = falcon.API(
        media_type='application/json',
        middleware=[
            AuthMiddleWare(),
        ],
    )

    #have our custom json handler here
    handlers = media.Handlers({
        'application/json': CustomJSONHandler(),
    })
    #register the custom handler here
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    #add custom error handler
    app.add_error_handler(falcon.HTTPError, handler=api_error_handler)

    #add routes
    for up in URL_PATTERNS:
        for i in up:
            app.add_route(i[0], i[1])
            #print("Link URL ",i[0],)

    return app
Ejemplo n.º 5
0
def test_json_err_no_handler(asgi, monkeypatch_resolver):
    app = create_app(asgi)

    handlers = media.Handlers(
        {falcon.MEDIA_URLENCODED: media.URLEncodedFormHandler()})

    # NOTE(kgriffs): Test the pre-3.0 method. Although undocumented, it was
    #   technically a public method, and so we make sure it still works here.
    if monkeypatch_resolver:

        def _resolve(media_type, default, raise_not_found=True):
            with pytest.warns(DeprecatedWarning,
                              match='This undocumented method'):
                h = handlers.find_by_media_type(
                    media_type, default, raise_not_found=raise_not_found)
            return h, None, None

        handlers._resolve = _resolve

    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            raise falcon.HTTPForbidden()

    app.add_route('/', Resource())

    result = testing.simulate_get(app, '/')
    assert result.status_code == 403
    assert result.json == falcon.HTTPForbidden().to_dict()
Ejemplo n.º 6
0
    def __init__(self):
        handlers = media.Handlers({
            'application/json': media.JSONHandler()
        })
        self.db_middleware = DatabaseMiddleware()
        self.config_middleware = ConfigMiddleware()
        self.validation_middleware = ValidationMiddleware()
        self.negotiation_middleware = NegotiationMiddleware()
        self.user_middleware = UserMiddleware()

        self.api = falcon.API(middleware=[
            self.config_middleware, self.db_middleware, self.user_middleware,
            self.validation_middleware, self.negotiation_middleware
        ])
        self.api.req_options.media_handlers = handlers
        self.api.req_options.auto_parse_form_urlencoded = True
        self.api.resp_options.media_handlers = handlers
        self.api.add_error_handler(Exception, error_handler)
        self.api.resp_options.secure_cookies_by_default = False

        # Routes
        dir_path = os.path.dirname(os.path.realpath(__file__))
        # Home route
        self.api.add_route('/app/home', HomeResource())
        # User routes
        self.api.add_route('/app/create', UserCreateResource())
        self.api.add_route('/app/create_email_exists',
                           UserCreateEmailExistsResource())
        self.api.add_route('/app/login', UserLoginResource())
        self.api.add_route('/app/login_failed', UserLoginFailedResource())
        self.api.add_route('/app/session_expired', SessionExpiredResource())
        self.api.add_route('/app/logout', UserLogoutResource())
        self.api.add_route('/api/users', UserCollectionResource())
        # Session routes
        self.api.add_route('/api/session', SessionResource())
        # Pomodoro routes
        self.api.add_route('/app/pomodoro', PomodoroResource())
        self.api.add_route('/app/pomodoro_set', PomodoroSetResource())
        self.api.add_route('/app/pom_exists', PomodoroExistsErrorResource())
        self.api.add_route('/app/pom_invalid',
                           PomodoroValidationErrorResource())
        self.api.add_route('/api/pom_validation', PomodoroValidationResource())
        self.api.add_route('/api/poms/today',
                           PomodoroCollectionTodayResource())
        self.api.add_route('/api/poms', PomodoroCollectionResource())
        self.api.add_route('/api/delete_poms', DeletePomsResource())
        self.api.add_route('/api/flag_types', FlagTypesResource())
        self.api.add_route('/api/pom_sheet_export', PomSheetExportResource())
        self.api.add_route('/app/export_poms', ExportPomsResource())
        # Settings route
        self.api.add_route('/app/settings', UserSettingsResource())
        # Static directory routes
        self.api.add_static_route('/css', dir_path + '/css')
        self.api.add_static_route('/js', dir_path + '/js')
        self.api.add_static_route('/assets', dir_path + '/assets')
Ejemplo n.º 7
0
def test_deserialization_raises(asgi):
    app = create_app(asgi)

    class SuchException(Exception):
        pass

    class FaultyHandler(media.BaseHandler):
        def deserialize(self, stream, content_type, content_length):
            raise SuchException('Wow such error.')

        def deserialize_async(self, stream, content_type, content_length):
            raise SuchException('Wow such error.')

        def serialize(self, media, content_type):
            raise SuchException('Wow such error.')

    handlers = media.Handlers({'application/json': FaultyHandler()})
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            resp.media = {}

        def on_post(self, req, resp):
            req.media

    class ResourceAsync:
        async def on_get(self, req, resp):
            resp.media = {}

        async def on_post(self, req, resp):
            # NOTE(kgriffs): In this one case we use the property
            #   instead of get_media(), in order to test that the
            #   alias works as expected.
            await req.media

    app.add_route('/', ResourceAsync() if asgi else Resource())

    # NOTE(kgriffs): Now that we install a default handler for
    #   Exception, we have to clear them to test the path we want
    #   to trigger.
    # TODO(kgriffs): Since we always add a default error handler
    #   for Exception, should we take out the checks in the WSGI/ASGI
    #   callable and just always assume it will be handled? If so,
    #   it makes testing that the right exception is propagated harder;
    #   I suppose we'll have to look at what is logged.
    app._error_handlers.clear()

    with pytest.raises(SuchException):
        testing.simulate_get(app, '/')

    with pytest.raises(SuchException):
        testing.simulate_post(app, '/', json={})
Ejemplo n.º 8
0
    def _factory(options):
        multipart_handler = media.MultipartFormHandler()
        for key, value in options.items():
            setattr(multipart_handler.parse_options, key, value)
        handlers = media.Handlers({
            falcon.MEDIA_JSON: media.JSONHandler(),
            falcon.MEDIA_MULTIPART: multipart_handler,
        })

        app = falcon.App()
        app.req_options.media_handlers = handlers
        app.add_route('/media', MultipartAnalyzer())

        return testing.TestClient(app)
Ejemplo n.º 9
0
def client():
    handlers = media.Handlers({
        falcon.MEDIA_JSON:
        media.JSONHandler(),
        falcon.MEDIA_URLENCODED:
        media.URLEncodedFormHandler(),
    })
    api = falcon.API()
    api.req_options.media_handlers = handlers
    api.resp_options.media_handlers = handlers

    api.add_route('/media', MediaMirror())

    return testing.TestClient(api)
Ejemplo n.º 10
0
def test_json_err_no_handler(asgi):
    app = create_app(asgi)

    handlers = media.Handlers({falcon.MEDIA_URLENCODED: media.URLEncodedFormHandler()})
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            raise falcon.HTTPForbidden()

    app.add_route('/', Resource())

    result = testing.simulate_get(app, '/')
    assert result.status_code == 403
    assert result.json == falcon.HTTPForbidden().to_dict()
Ejemplo n.º 11
0
def test_deserialize_custom_media(custom_client):
    class FirstByteHandler(media.BaseHandler):
        exhaust_stream = True

        def deserialize(self, stream, content_type, content_length):
            first_byte = stream.read(1)
            if first_byte:
                return '0x{:02x}'.format(first_byte[0])
            return ''

        async def deserialize_async(self, stream, content_type,
                                    content_length):
            first_byte = await stream.read(1)
            if first_byte:
                return '0x{:02x}'.format(first_byte[0])
            return ''

    handlers = media.Handlers(
        {'application/x-falcon-first-byte': FirstByteHandler()})
    client = custom_client({'media_handlers': handlers})

    data = (b'--BOUNDARY\r\n'
            b'Content-Disposition: form-data; name="first"\r\n'
            b'Content-Type: application/x-falcon-first-byte\r\n\r\n'
            b'\r\n'
            b'--BOUNDARY\r\n'
            b'Content-Disposition: form-data; name="second"\r\n'
            b'Content-Type: application/x-falcon-first-byte\r\n\r\n'
            b'Hi!\r\n'
            b'--BOUNDARY--\r\n')

    resp = client.simulate_post(
        '/media',
        headers={'Content-Type': 'multipart/form-data; boundary=BOUNDARY'},
        body=data,
    )

    assert resp.status_code == 200
    assert resp.json == ['', '0x48']
Ejemplo n.º 12
0
def test_async_handler_returning_none():
    app = create_app(asgi=True)

    class SimpleHandler(media.BaseHandler):
        def serialize(self, media, content_type):
            return json.dumps(media).encode()

        def deserialize(self, stream, content_type, content_length):
            return None

    handlers = media.Handlers({'application/json': SimpleHandler()})
    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class ResourceAsync:
        async def on_post(self, req, resp):
            resp.media = [await req.get_media()]

    app.add_route('/', ResourceAsync())

    doc = {'event': 'serialized'}
    result = testing.simulate_post(app, '/', json=doc)
    assert result.status_code == 200
    assert result.json == [None]
Ejemplo n.º 13
0
import falcon
from falcon import media
from middleware import SqlAlchemySessionManager, SqlAlchemyMediaHandler, Session
import resources

handlers = media.Handlers({
    'application/json': SqlAlchemyMediaHandler,
})
app = falcon.API(middleware=[SqlAlchemySessionManager(Session)])
app.resp_options.media_handlers = handlers
app.add_route('/cats', resources.CatsRessource())
app.add_route('/cats/{id}', resources.CatRessource())
Ejemplo n.º 14
0
from look.api import auth, db, gql
from look.middleware.requestdatamanager import RequetDataManager
from look.middleware.dbmanager import DBManager
from look.middleware.socketmanager import SocketManager
from look.schema import schema

from falcon import media
from falcon.media import MultipartFormHandler
from falcon.media.multipart import MultipartParseOptions

db_session, engine = init_db()

parse_options = MultipartParseOptions()
parse_options.max_body_part_buffer_size = 3 * 1024 * 1024
handlers = media.Handlers({
    'multipart/form-data':
    MultipartFormHandler(parse_options=parse_options),
})

middleware = [
    RequetDataManager(),
    DBManager(db_session, schema),
]

app = application = falcon.asgi.App(middleware=middleware)

app.req_options.strip_url_path_trailing_slash = True
app.req_options.media_handlers.update(handlers)
app.resp_options.media_handlers.update(handlers)


class RootPage(object):
Ejemplo n.º 15
0
        Delivers data for a particular luftdaten.info sensor
        """
        url = "http://api.luftdaten.info/v1/sensor/%s/" % sensor_id
        r = requests.get(url)

        if r.status_code == 200:
            maxage = 60 * 5  # 5 minutes
            resp.cache_control = ["max_age=%d" % maxage]
            resp.media = r.json()
        else:
            resp.media = r.text
            resp.status = str(r.status_code) + " Unknown Error"


handlers = media.Handlers({
    'application/json': jsonhandler.JSONHandler(),
})

cors = CORS(allow_all_origins=True, allow_all_headers=True)

app = falcon.API(middleware=[cors.middleware])

app.req_options.media_handlers = handlers
app.resp_options.media_handlers = handlers

app.add_route('/events/', EventsResource())
app.add_route('/feed/', FeedResource())
app.add_route('/luftdaten.info/v1/sensor/{sensor_id}/',
              ParticleSensorResource())
app.add_route('/', IndexResource())
Ejemplo n.º 16
0
def test_deserialization_raises(asgi, handler_mt, monkeypatch_resolver):
    app = create_app(asgi)

    class SuchException(Exception):
        pass

    class FaultyHandler(media.BaseHandler):
        def deserialize(self, stream, content_type, content_length):
            raise SuchException('Wow such error.')

        def deserialize_async(self, stream, content_type, content_length):
            raise SuchException('Wow such error.')

        def serialize(self, media, content_type):
            raise SuchException('Wow such error.')

    handlers = media.Handlers({handler_mt: FaultyHandler()})

    # NOTE(kgriffs): Test the pre-3.0 method. Although undocumented, it was
    #   technically a public method, and so we make sure it still works here.
    if monkeypatch_resolver:

        def _resolve(media_type, default, raise_not_found=True):
            with pytest.warns(DeprecatedWarning,
                              match='This undocumented method'):
                h = handlers.find_by_media_type(
                    media_type, default, raise_not_found=raise_not_found)
            return h, None, None

        handlers._resolve = _resolve

    app.req_options.media_handlers = handlers
    app.resp_options.media_handlers = handlers

    class Resource:
        def on_get(self, req, resp):
            resp.media = {}

        def on_post(self, req, resp):
            req.media

    class ResourceAsync:
        async def on_get(self, req, resp):
            resp.media = {}

        async def on_post(self, req, resp):
            # NOTE(kgriffs): In this one case we use the property
            #   instead of get_media(), in order to test that the
            #   alias works as expected.
            await req.media

    app.add_route('/', ResourceAsync() if asgi else Resource())

    # NOTE(kgriffs): Now that we install a default handler for
    #   Exception, we have to clear them to test the path we want
    #   to trigger.
    # TODO(kgriffs): Since we always add a default error handler
    #   for Exception, should we take out the checks in the WSGI/ASGI
    #   callable and just always assume it will be handled? If so,
    #   it makes testing that the right exception is propagated harder;
    #   I suppose we'll have to look at what is logged.
    app._error_handlers.clear()

    with pytest.raises(SuchException):
        testing.simulate_get(app, '/')

    with pytest.raises(SuchException):
        testing.simulate_post(app, '/', json={})
Ejemplo n.º 17
0
    def __init__(self, path, resource_resolver, **kwargs):
        spec = Object.from_file(OpenApi, path)

        middleware = list(kwargs.pop('middleware', []))
        middleware.append(ValidationMiddleware())

        request_type = kwargs.pop('request_type', None)
        assert request_type is None or issubclass(
            request_type, FalconHeavyRequest), (
                "Request type MUST be subclass of `FalconHeavyRequest`")

        request_type = request_type or FalconHeavyRequest

        response_type = kwargs.pop('response_type', None)
        assert response_type is None or issubclass(
            response_type, FalconHeavyResponse), (
                "Response type MUST be subclass of `FalconHeavyResponse`")

        response_type = response_type or FalconHeavyResponse

        super(FalconHeavyApi, self).__init__(middleware=middleware,
                                             request_type=request_type,
                                             response_type=response_type,
                                             **kwargs)

        self.req_options = FalconHeavyRequestOptions()

        self.req_options.keep_blank_qs_values = True
        self.req_options.auto_parse_qs_csv = False
        self.req_options.auto_parse_form_urlencoded = False

        self.add_error_handler(FalconHeavyHTTPError)

        # Replace standard media handlers in the responses to serialize
        # the date and date-time objects according to the specification
        self.resp_options.media_handlers = media.Handlers({
            'application/json':
            FalconHeavyJSONHandler(),
            'application/json; charset=UTF-8':
            FalconHeavyJSONHandler(),
        })

        for uri_template, path_item in iteritems(spec['paths']):
            resource_id = path_item['x-resource']
            lazy = resource_resolver.resolve(resource_id)

            if lazy is None:
                logger.error("Resource `%s` is not resolved. Skip path `%s`",
                             resource_id, uri_template)
                continue

            assert callable(
                lazy), "Resource `{}` MUST be resolved as callable".format(
                    resource_id)

            operation_schemas = {}
            for http_method in falcon.HTTP_METHODS:
                operation = path_item.get(http_method.lower())
                if operation is None:
                    continue

                operation_schema = operation_schemas.setdefault(
                    http_method, {})

                parameters = operation.get('parameters')
                if parameters is not None:
                    operation_schema[
                        'parameters'] = ParametersFactory.generate(parameters)

                request_body = operation.get('requestBody')
                if request_body is not None:
                    operation_schema[
                        'requestBody'] = RequestBodyFactory.generate(
                            request_body)

                operation_schema['responses'] = ResponsesFactory.generate(
                    operation['responses'])
                operation_schema['security'] = operation.get('security')

            resource = lazy()
            assert resource, "Resource `{}` is not instantiated".format(
                resource_id)

            setattr(resource, '__operation_schemas', operation_schemas)
            self.add_route(uri_template, resource)
Ejemplo n.º 18
0
def create_app(infer, metric_registry, health_check, req_schema, resp_schema,
               use_msgpack, config):
    """
    create :class:`falcon` application

    :param infer: model infer function (contains `preprocess`, `inference`, and `postprocess`)
    :param metric_registry: Prometheus metric registry
    :param health_check: model health check function (need examples provided in schema)
    :param req_schema: request schema defined with :class:`pydantic.BaseModel`
    :param resp_schema: request schema defined with :class:`pydantic.BaseModel`
    :param bool use_msgpack: use msgpack for serialization or not (default: JSON)
    :param config: configs :class:`ventu.config.Config`
    :return: a :class:`falcon` application
    """
    if use_msgpack:
        handlers = media.Handlers({
            'application/msgpack':
            media.MessagePackHandler(),
        })
        app = API(media_type='application/msgpack')
        app.req_options.media_handlers = handlers
        app.resp_options.media_handlers = handlers
    else:
        app = API()

    api = SpecTree('falcon', title=config.name, version=config.version)
    logger = logging.getLogger(__name__)
    VALIDATION_ERROR_COUNTER = Counter(
        'validation_error_counter',
        'numbers of validation errors',
        registry=metric_registry,
    )

    def counter_hook(req, resp, resource):
        if resp.status == HTTP_422:
            VALIDATION_ERROR_COUNTER.inc()

    class Homepage:
        def on_get(self, req, resp):
            logger.debug('return service endpoints')
            resp.media = {
                'health check': {
                    '/health': 'GET'
                },
                'metrics': {
                    '/metrics': 'GET'
                },
                'inference': {
                    '/inference': 'POST'
                },
                'API document': {
                    '/apidoc/redoc': 'GET',
                    '/apidoc/swagger': 'GET'
                }
            }

    class Metrics:
        def __init__(self):
            if os.environ.get('prometheus_multiproc_dir'):
                multiprocess.MultiProcessCollector(metric_registry)

        def on_get(self, req, resp):
            resp.content_type = CONTENT_TYPE_LATEST
            resp.body = generate_latest(metric_registry)

    class HealthCheck:
        @api.validate(resp=Response(HTTP_200=ServiceStatus))
        def on_get(self, req, resp):
            """
            Health check
            """
            status = ServiceStatus(inference=StatusEnum.ok)
            try:
                health_check()
            except AssertionError as err:
                status.inference = StatusEnum.error
                logger.warning(f'Service health check error: {err}')
            logger.debug(str(status))
            resp.media = status.dict()

    class Inference:
        @after(counter_hook)
        @api.validate(json=req_schema, resp=Response(HTTP_200=resp_schema))
        def on_post(self, req, resp):
            """
            Deep learning model inference
            """
            data = req.context.json
            logger.debug(str(data))
            resp.media = infer(data)

    app.add_route('/', Homepage())
    app.add_route('/health', HealthCheck())
    app.add_route('/metrics', Metrics())
    app.add_route('/inference', Inference())
    api.register(app)
    return app