예제 #1
0
def test_invalid_operation_does_not_stop_application_in_debug_mode():
    api = FlaskApi(TEST_FOLDER / "fixtures/op_error_api/swagger.yaml",
                   base_path="/api/v1.0",
                   arguments={'title': 'OK'},
                   debug=True)
    assert api.specification['info']['title'] == 'OK'

    api = FlaskApi(TEST_FOLDER / "fixtures/missing_op_id/swagger.yaml",
                   base_path="/api/v1.0",
                   arguments={'title': 'OK'},
                   debug=True)
    assert api.specification['info']['title'] == 'OK'

    api = FlaskApi(TEST_FOLDER /
                   "fixtures/module_not_implemented/swagger.yaml",
                   base_path="/api/v1.0",
                   arguments={'title': 'OK'},
                   debug=True)
    assert api.specification['info']['title'] == 'OK'

    api = FlaskApi(TEST_FOLDER /
                   "fixtures/user_module_loading_error/swagger.yaml",
                   base_path="/api/v1.0",
                   arguments={'title': 'OK'},
                   debug=True)
    assert api.specification['info']['title'] == 'OK'
예제 #2
0
def test_invalid_operation_does_stop_application_to_setup():
    with pytest.raises(ImportError):
        FlaskApi(TEST_FOLDER / "fixtures/op_error_api/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})

    with pytest.raises(ResolverError):
        FlaskApi(TEST_FOLDER / "fixtures/missing_op_id/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})

    with pytest.raises(ImportError):
        FlaskApi(TEST_FOLDER / "fixtures/module_not_implemented/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})

    with pytest.raises(ValueError):
        FlaskApi(TEST_FOLDER /
                 "fixtures/user_module_loading_error/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})

    with pytest.raises(ResolverError):
        FlaskApi(TEST_FOLDER / "fixtures/missing_op_id/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})
예제 #3
0
def test_api():
    api = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml", base_path="/api/v1.0")
    assert api.blueprint.name == '/api/v1_0'
    assert api.blueprint.url_prefix == '/api/v1.0'

    api2 = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml")
    assert api2.blueprint.name == '/v1_0'
    assert api2.blueprint.url_prefix == '/v1.0'
예제 #4
0
def test_template():
    api1 = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml",
                    base_path="/api/v1.0", arguments={'title': 'test'})
    assert api1.specification['info']['title'] == 'test'

    api2 = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml",
                    base_path="/api/v1.0", arguments={'title': 'other test'})
    assert api2.specification['info']['title'] == 'other test'
예제 #5
0
def test_api():
    api = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml", "/api/v1.0",
                   {})
    assert api.blueprint.name == '/api/v1_0'
    assert api.blueprint.url_prefix == '/api/v1.0'
    # TODO test base_url in spec

    api2 = FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml")
    assert api2.blueprint.name == '/v1_0'
    assert api2.blueprint.url_prefix == '/v1.0'
예제 #6
0
def test_other_errors_stop_application_to_setup():
    # Errors should still result exceptions!
    with pytest.raises(InvalidSpecification):
        FlaskApi(TEST_FOLDER / "fixtures/bad_specs/swagger.yaml",
                 base_path="/api/v1.0", arguments={'title': 'OK'})

    # Debug mode should ignore the error
    api = FlaskApi(TEST_FOLDER / "fixtures/bad_specs/swagger.yaml",
                   base_path="/api/v1.0", arguments={'title': 'OK'}, debug=True)
    assert api.specification['info']['title'] == 'OK'
예제 #7
0
def test_other_errors_stop_application_to_setup():
    # The previous tests were just about operationId not being resolvable.
    # Other errors should still result exceptions!
    with pytest.raises(InvalidSpecification):
        FlaskApi(TEST_FOLDER / "fixtures/bad_specs/swagger.yaml", "/api/v1.0",
                 {'title': 'OK'})

    # Debug mode should ignore the error
    api = FlaskApi(TEST_FOLDER / "fixtures/bad_specs/swagger.yaml",
                   "/api/v1.0", {'title': 'OK'},
                   debug=True)
    assert api.specification['info']['title'] == 'OK'
예제 #8
0
def common_error_handler(exception: BaseException) -> flask.Response:
    """Used to capture connexion exceptions and add link to the type field."""
    if isinstance(exception, ProblemException):

        link = EXCEPTIONS_LINK_MAP.get(exception.status)
        if link:
            response = problem(
                status=exception.status,
                title=exception.title,
                detail=exception.detail,
                type=link,
                instance=exception.instance,
                headers=exception.headers,
                ext=exception.ext,
            )
        else:
            response = problem(
                status=exception.status,
                title=exception.title,
                detail=exception.detail,
                type=exception.type,
                instance=exception.instance,
                headers=exception.headers,
                ext=exception.ext,
            )
    else:
        if not isinstance(exception, werkzeug.exceptions.HTTPException):
            exception = werkzeug.exceptions.InternalServerError()

        response = problem(title=exception.name,
                           detail=exception.description,
                           status=exception.code)

    return FlaskApi.get_response(response)
예제 #9
0
파일: views.py 프로젝트: cyBerta/api
def register(app):
    from measurements import api

    connexion_resolver = Resolver()
    connexion_api = FlaskApi(
        specification=pathlib.Path(
            os.path.join(HERE, "openapi/measurements.yml")),
        resolver=connexion_resolver,
        arguments=dict(),
        swagger_json=True,
        swagger_ui=False,
        swagger_path=None,
        swagger_url=None,
        resolver_error_handler=None,
        validate_responses=False,
        strict_validation=True,
        auth_all_paths=False,
        debug=True,
        validator_map=None,
    )

    app.register_blueprint(api_docs_blueprint, url_prefix="/api")
    app.register_blueprint(connexion_api.blueprint)
    app.register_blueprint(api_private_blueprint, url_prefix="/api/_")
    app.register_blueprint(pages_blueprint, url_prefix="")

    app.register_error_handler(ProblemException, render_problem_exception)
    app.register_error_handler(Exception, render_generic_exception)

    app.errorhandler(404)(page_not_found)
    app.errorhandler(400)(bad_request)
예제 #10
0
    def common_error_handler(exception):
        """
        :type exception: Exception
        """
        if isinstance(exception, ProblemException):
            # exception.title show message like 'Bad Request' which is not very helpful
            response = ErrorHanlder.problem(status=exception.status,
                                            title=exception.detail,
                                            detail=exception.detail,
                                            type=exception.type,
                                            instance=exception.instance,
                                            headers=exception.headers,
                                            ext=exception.ext)

        elif isinstance(exception, ServiceException):
            response = ErrorHanlder.problem(status=exception.error_code,
                                            title=exception.error_title,
                                            detail=exception.error_msg)
        else:
            if not isinstance(exception, werkzeug.exceptions.HTTPException):
                common_exception = werkzeug.exceptions.InternalServerError()
                if os.getenv('FLASK_CONFIG', 'development') == 'development':
                    raise exception
                response = ErrorHanlder.problem(
                    title=common_exception.name,
                    detail=common_exception.description,
                    ext=str(exception),
                    status=common_exception.code)
            else:
                response = ErrorHanlder.problem(title=exception.name,
                                                detail=exception.description,
                                                ext=str(exception),
                                                status=exception.code)
        traceback.print_exc()
        return FlaskApi.get_response(response)
예제 #11
0
def test_invalid_encoding():
    with tempfile.NamedTemporaryFile(mode='wb') as f:
        f.write(
            u"swagger: '2.0'\ninfo:\n  title: Foo 整\n  version: v1\npaths: {}".
            encode('gbk'))
        f.flush()
        FlaskApi(pathlib.Path(f.name), base_path="/api/v1.0")
예제 #12
0
def test_use_of_safe_load_for_yaml_swagger_specs():
    with pytest.raises(YAMLError):
        with tempfile.NamedTemporaryFile(delete=False) as f:
            f.write('!!python/object:object {}\n'.encode())
        try:
            FlaskApi(pathlib.Path(f.name), base_path="/api/v1.0")
            os.unlink(f.name)
        except InvalidSpecification:
            pytest.fail("Could load invalid YAML file, use yaml.safe_load!")
예제 #13
0
def test_use_of_safe_load_for_yaml_swagger_specs():
    with pytest.raises(YAMLError):
        with tempfile.NamedTemporaryFile() as f:
            f.write('!!python/object:object {}\n'.encode())
            f.flush()
            try:
                FlaskApi(pathlib.Path(f.name), base_path="/api/v1.0")
            except SwaggerValidationError:
                pytest.fail("Could load invalid YAML file, use yaml.safe_load!")
예제 #14
0
def exception_handler(exception):
    log.critical("{}:{}:{}-{}".format(
        getattr(exception, 'name', 'uncaught'),
        getattr(exception, 'code', 500),
        getattr(exception, 'description', 'uncaught'),
        getattr(exception, 'type', 'about:blank')))

    trace_exception(exception, log)

    response = problem(title=getattr(exception, 'name', 'uncaught'),
                       status=getattr(exception, 'code', 500),
                       detail=getattr(exception, 'description', 'uncaught'),
                       type=getattr(exception, 'type', 'about:blank'))
    return FlaskApi.get_response(response)
예제 #15
0
def handle_phabricator_api_exception(exc):
    sentry.captureException()
    logger.error('phabricator exception',
                 extra={
                     'error_code': exc.error_code,
                     'error_info': exc.error_info,
                 },
                 exc_info=exc)
    return FlaskApi.get_response(
        problem(
            500,
            'Phabricator Error',
            'An unexpected error was received from Phabricator',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500'
        ))
def handle_phabricator_api_exception(exc):
    sentry.captureException()
    logger.error(
        "phabricator exception",
        extra={"error_code": exc.error_code, "error_info": exc.error_info},
        exc_info=exc,
    )
    return FlaskApi.get_response(
        problem(
            500,
            "Phabricator Error",
            "An unexpected error was received from Phabricator",
            type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500",
        )
    )
예제 #17
0
 def log_error(self, exception):
     _, exc_val, exc_tb = sys.exc_info()
     if hasattr(exception, 'name'):
         resp = problem(
             title=exception.name,
             detail=exception.description,
             status=exception.code,
         )
     else:
         resp = problem(
             title=repr(exc_val),
             detail=''.join(traceback.format_tb(exc_tb)),
             status=500,
         )
     return FlaskApi.get_response(resp)
예제 #18
0
def handle_treestatus_exception(exc):
    sentry.captureException()
    logger.error("Tree Status exception", exc_info=exc)

    if current_app.propagate_exceptions:
        # Mimic the behaviour of Flask.handle_exception() and re-raise the full
        # traceback in test and debug environments.
        raise exc

    return FlaskApi.get_response(
        problem(
            500,
            "Tree Status Error",
            "An unexpected error was received from Tree Status",
            type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500",
        ))
예제 #19
0
파일: rest_api.py 프로젝트: surajrb/checkmk
 def _make_error_response(self, exception):
     exc_info = sys.exc_info()
     logger.exception("Exception caught", exc_info=exc_info)
     _, exc_val, exc_tb = exc_info
     if hasattr(exception, 'to_problem'):
         resp = exception.to_problem()
     elif hasattr(exception, 'name'):
         resp = problem(
             title=exception.name,
             detail=exception.description,
             status=exception.code,
         )
     else:
         resp = problem(
             title=repr(exc_val),
             detail=''.join(traceback.format_tb(exc_tb)),
             status=500,
         )
     return FlaskApi.get_response(resp)
예제 #20
0
파일: views.py 프로젝트: cyBerta/api
def render_generic_exception(exception):
    if not isinstance(exception, werkzeug.exceptions.HTTPException):
        exc_name = "{}.{}".format(
            type(exception).__module__,
            type(exception).__name__)
        exc_desc = str(exception)
        if hasattr(exception, "__traceback__"):
            current_app.logger.error("".join(
                traceback.format_tb(exception.__traceback__)))
        current_app.logger.error("Unhandled error occurred, {}: {}".format(
            exc_name, exc_desc))
        exception = werkzeug.exceptions.InternalServerError(
            description="An unhandled application error occurred: {}".format(
                exc_name))

    response = problem(title=exception.name,
                       detail=exception.description,
                       status=exception.code)
    return FlaskApi.get_response(response)
예제 #21
0
파일: hooks.py 프로젝트: cgsheeh/lando-api
def handle_phabricator_api_exception(exc):
    sentry.captureException()
    logger.error(
        "phabricator exception",
        extra={"error_code": exc.error_code, "error_info": exc.error_info},
        exc_info=exc,
    )

    if current_app.propagate_exceptions:
        # Mimic the behaviour of Flask.handle_exception() and re-raise the full
        # traceback in test and debug environments.
        raise exc

    return FlaskApi.get_response(
        problem(
            500,
            "Phabricator Error",
            "An unexpected error was received from Phabricator",
            type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500",
        )
    )
예제 #22
0
def connexion_error_handler(exception: Exception):
    """Handle exception from request process"""
    if flask.has_request_context:
        ext = {"request_id": request_id()}
    else:
        ext = None
    if isinstance(exception, ProblemException):
        if ext:
            if exception.ext is None:
                exception.ext = ext
            else:
                exception.ext.update(ext)
        response = exception.to_problem()
        extra = {
            "status": exception.status,
            "title": exception.title,
            "detail": exception.detail,
        }
        status_code = exception.status
        log_func = _status2log(exception.status, response_logger)
    else:
        if not isinstance(exception, HTTPException):
            exception = InternalServerError()
        response = problem(
            title=exception.name,
            detail=exception.description,
            status=exception.code,
            ext=ext,
        )
        extra = {
            "status": exception.code,
            "title": exception.name,
            "detail": exception.description,
        }
        status_code = exception.code

    log_func = _status2log(status_code, response_logger)
    log_func("HTTP error (%d)", response.status_code, extra=extra)

    return FlaskApi.get_response(response)
예제 #23
0
def test_validation_error_on_completely_invalid_swagger_spec():
    with tempfile.NamedTemporaryFile(delete=False) as f:
        f.write('[1]\n'.encode())
    with pytest.raises(InvalidSpecification):
        FlaskApi(pathlib.Path(f.name), base_path="/api/v1.0")
    os.unlink(f.name)
예제 #24
0
def test_api_base_path_slash():
    api = FlaskApi(TEST_FOLDER / "fixtures/simple/basepath-slash.yaml")
    assert api.blueprint.name == ''
    assert api.blueprint.url_prefix == ''
예제 #25
0
def test_warn_users_about_base_url_parameter_name_change(mock_api_logger):
    FlaskApi(TEST_FOLDER / "fixtures/simple/swagger.yaml", base_url="/api/v1")
    mock_api_logger.warning.assert_called_with(
        'Parameter base_url should be no longer used. Use base_path instead.')
예제 #26
0
def test_validation_error_on_completely_invalid_swagger_spec():
    with pytest.raises(SwaggerValidationError):
        with tempfile.NamedTemporaryFile() as f:
            f.write('[1]\n'.encode())
            f.flush()
            FlaskApi(pathlib.Path(f.name), base_path="/api/v1.0")
예제 #27
0
def problem_exception_handler(exception):
    log.error("{}:{}:{}-{}".format(exception.title, exception.status,
                                   exception.detail, exception.type))
    trace_exception(exception, log)
    response = exception.to_problem()
    return FlaskApi.get_response(response)
예제 #28
0
def test_invalid_schema_file_structure():
    with pytest.raises(SwaggerValidationError):
        FlaskApi(TEST_FOLDER / "fixtures/invalid_schema/swagger.yaml",
                 base_path="/api/v1.0", arguments={'title': 'OK'}, debug=True)
예제 #29
0
파일: views.py 프로젝트: cyBerta/api
def render_problem_exception(exception):
    response = exception.to_problem()
    return FlaskApi.get_response(response)
예제 #30
0
def test_other_errors_stop_application_to_setup():
    # Errors should still result exceptions!
    with pytest.raises(InvalidSpecification):
        FlaskApi(TEST_FOLDER / "fixtures/bad_specs/swagger.yaml",
                 base_path="/api/v1.0",
                 arguments={'title': 'OK'})