This PR adds an `add_middleware` method to the apps and
`ConnexionMiddleware` to easily add middleware to the stack. Before, the
only way to do this was to pass in a complete middleware stack.
The default position to add the new middleware is right before the
`ContextMiddleware`, which is the final middleware in the stack. Another
position can be selected by passing in a `MiddlewarePosition` enum,
which defines some positions which make sense.
Since we can no longer assume that the whole middleware stack is defined
when initializing the `ConnexionMiddleware`, we need to delay building
the middleware stack until the `ConnexionMiddleware` is actually called.
This also means we need to delay registering the APIs and error
handlers. This is now all done in the `_build_middleware_stack` method.
This PR updates the examples for Connexion 3.0 and merges them for
OpenAPI and Swagger.
2 examples required some changes to make them work:
- The reverse proxy example required some fixes to the
SwaggerUIMiddleware to leverage the `root_path` correctly. This is
included in the PR.
- The enforced defaults example requires the json validator to adapt the
body and pass it on. We currently pass on the original body after
validation, and I'm not sure if we should change this. I'll submit a
separate PR to discuss this.
* Revert "set max aiohttp version to 3.5.1 (until build is fixed) (#844)"
This reverts commit b2a4287405.
* Fix test_run_with_aiohttp_not_installed
Somewhere between 3.5.1 and 3.5.2, the aiohttp reimport started
succeeding (in connexion.connexion.cli.run()). It's not clear which
change caused the issue, but it's probably one of:
- aio-libs/aiohttp#3469 (Remove wildcard imports)
- aio-libs/aiohttp#3464 (Don't suppress gunicorn cleanup errors)
- aio-libs/aiohttp#3471 (Refactor workers)
- aio-libs/aiohttp#3500 (Ignore done tasks)
In any case, setting sys.modules['aiohttp'] = None should prevent
reimporting it. See: https://stackoverflow.com/a/1350574
I successfully tested locally on py37 with aiohttp 3.5.1 and 3.5.2.
Fixes the build.
Changes proposed in this pull request:
- apply all of the isort changes that resulted from the latest version
- pin to the latest version (4.3.15) so this doesn't happen again, unless we bump the version on purpose
- App and Api options must be provided through the "options" argument (``old_style_options`` have been removed).
- You must specify a form content-type in 'consumes' in order to consume form data.
- The `Operation` interface has been formalized in the `AbstractOperation` class.
- The `Operation` class has been renamed to `Swagger2Operation`.
- Array parameter deserialization now follows the Swagger 2.0 spec more closely.
In situations when a query parameter is passed multiple times, and the collectionFormat is either csv or pipes, the right-most value will be used.
For example, `?q=1,2,3&q=4,5,6` will result in `q = [4, 5, 6]`.
The old behavior is available by setting the collectionFormat to `multi`, or by importing `decorators.uri_parsing.AlwaysMultiURIParser` and passing `parser_class=AlwaysMultiURIParser` to your Api.
- The spec validator library has changed from `swagger-spec-validator` to `openapi-spec-validator`.
- Errors that previously raised `SwaggerValidationError` now raise the `InvalidSpecification` exception.
All spec validation errors should be wrapped with `InvalidSpecification`.
- Support for nullable/x-nullable, readOnly and writeOnly/x-writeOnly has been added to the standard json schema validator.
- Custom validators can now be specified on api level (instead of app level).
- Added support for basic authentication and apikey authentication
- If unsupported security requirements are defined or ``x-tokenInfoFunc``/``x-tokenInfoUrl`` is missing, connexion now denies requests instead of allowing access without security-check.
- Accessing ``connexion.request.user`` / ``flask.request.user`` is no longer supported, use ``connexion.context['user']`` instead
- Created a metaclass for AbstractAPI (it is used to set the jsonifier for the class);
- Created a new class method AbstractAPI._set_jsonifier;
- Changed the code to use the new jsonifier interface;
- Create a new module called coroutines_wrapper to put the wrapper functions with the 'yield from' statement. It is used to enable frameworks with coroutine handlers;
- Did the AioHttpApi.get_request coroutine and add req.read() to get the request body;
- Moved the flask jsonifier to utils and did it a generic jsonifier;
- Created a function called 'has_coroutine' on utils module;
- Added aiohttp_jinja2 to requirements-aiohttp;
- Added a new python3 coreragerc file to skip only python2 lines;
- Fixed the set of validation_response on test_aiohttp_simple_api.py;
- Added the test to check the aiohttp body request;
- Fixed the response for 'aiohttp_bytes_response' and 'aiohttp_non_str_non_json_response' paths on aiohttp/swagger_simple.yml file.
- created a new option called 'server'
- did wsgi-server option deprecated
- changed the app-cls option to app-framework
- fixed the possible frameworks that will run the app
- added a validation on framework/server selection
- Added the AioHttpApi and AioHttpApp on connexion __init__;
- Created an abstract method on AbstractApi to cast the framework response to connexion response;
- Implemented the get_connexion_response on FlaskApi;
- Changed the CLI to use any kind of App class;
- Changed the ResponseValidator to always convert the response to a connexion response;
- Changed the ResponseValidator to support coroutine responses;
- Added the aiohttp as optional dependency;
- Added ujson as optional dependency;
- Skipped the aiohttp tests run on python 2.7;
- Changed the tests configs to run aiohttp tests properly on python 3.4+.
removed test_decorators and test_parameter (this test is useless now);
removed the request/response containers and add new request response classes;
created a abstract api class and a api flask class;
derived classes will implements the get_response/get_request methods that will convert framework req/resp types to connexion req/resp types;
moved the jsonifier from produces to flask api;
created a abstract app class and a app flask class;
changed all validators to use the ConnexionRequest instead flask request;
changed the problem function to generate a ConnexionRequest;
created a new user variables container called context (this is a property of ConnexionRequest). this will be passed as kwargs to all operations functions;
this context is used on authentication;
fixed all tests to new API;
some changes that I did may not be documented in this commit.