Request handling¶
When your application receives a request, Connexion provides a lot of functionality based on your OpenAPI spec:
It checks the security (see Security)
It routes the request to the correct endpoint (see Routing)
It validates the body and parameters (see Validation)
It parses and passes the body and parameters to your python function
On this page, we zoom in on the final part.
Automatic parameter handling¶
Connexion automatically maps the parameters defined in your endpoint specification to the arguments defined your associated Python function, parsing and casting values when possible. All you need to do, is make sure the arguments of your function match the parameters in your specification.
Connexion automatically maps the parameters defined in your endpoint specification to the arguments defined your associated Python function, parsing and casting values when possible. All you need to do, is make sure the arguments of your function match the parameters in your specification.
Connexion can automatically map the parameters defined in your endpoint specification to the arguments defined your associated Python function, parsing and casting values when possible. All you need to do, is make sure the arguments of your function match the parameters in your specification.
To activate this behavior when using the ConnexionMiddleware
wrapping a third party
application, you can leverage the following decorators provided by Connexion:
WSGIDecorator
: provides automatic parameter injection for WSGI applications. Note that this decorator injects Werkzeug / Flask datastructures.FlaskDecorator
: provides automatic parameter injection and response serialization for Flask applications.ASGIDecorator
: provides automatic parameter injection for ASGI applications. Note that this decorator injects Starlette datastructures (such as UploadFile).StarletteDecorator
: provides automatic parameter injection and response serialization for Starlette applications.
from asgi_framework import App
from connexion import ConnexionMiddleware
from connexion.decorators import ASGIDecorator
@app.route("/greeting/<name>", methods=["POST"])
@ASGIDecorator()
def post_greeting(name):
...
app = App(__name__)
app = ConnexionMiddleware(app)
app.add_api("openapi.yaml")
For a full example, see our Frameworks example.
For example, if you have an endpoint specified as:
paths:
/foo:
get:
operationId: api.foo_get
parameters:
- name: message
description: Some message.
in: query
schema:
type: string
required: true
paths:
/foo:
get:
operationId: api.foo_get
parameters:
- name: message
description: Some message.
in: query
type: string
required: true
And the view function as:
def foo_get(message):
...
Connexion will automatically identify that your view function expects an argument named message
and will pass in the value of the endpoint parameter message
.
This works for both path and query parameters.
Body¶
The body will also be passed to your function.
In the OpenAPI 3 spec, the requestBody
does not have a name. By default it will be
passed into your function as body
. You can use x-body-name
in your operation to
override this name.
paths:
/foo:
post:
operationId: api.foo_get
requestBody:
x-body-name: payload
content:
application/json:
schema:
...
# Default
def foo_get(body)
...
# Based on x-body-name
def foo_get(payload)
...
In the Swagger 2 specification, you can define the name of your body. Connexion will pass the body to your function using this name.
paths:
/foo:
post:
consumes:
- application/json
parameters:
- in: body
name: payload
schema:
...
def foo_get(payload)
...
In Swagger 2, form data is defined as parameters in your specification, and Connexion passes these parameters individually:
paths:
/foo:
post:
operationId: api.foo_get
consumes:
- application/json
parameters:
- in: formData
name: field1
type: string
- in: formData
name: field2
type: string
def foo_get(field1, field2)
...
Connexion will not automatically pass in the default values defined in your requestBody
definition, but you can activate this by configuring a different
RequestBodyValidator.
Files¶
Connexion extracts the files from the body and passes them into your view function separately:
paths:
/foo:
post:
operationId: api.foo_get
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
In the Swagger 2 specification, you can define the name of your body. Connexion will pass the body to your function using this name.
paths:
/foo:
post:
consumes:
- application/json
parameters:
- name: file
type: file
in: formData
If you’re using the AsyncApp, the files are provided as Starlette.UploadFile instances.
def foo_get(file)
assert isinstance(file, starlette.UploadFile)
...
If you’re using the FlaskApp, the files are provided as werkzeug.FileStorage instances.
def foo_get(file)
assert isinstance(file, werkzeug.FileStorage)
...
When your specification defines an array of files:
type: array
items:
type: string
format: binary
They will be provided to your view function as a list.
Optional arguments & Defaults¶
If a default value is defined for a parameter in the OpenAPI specification, Connexion will automatically pass it in if no value was included in the request. If a default is defined in the specification, you should not define a default in your Python function, as it will never be triggered.
If an endpoint parameter is optional and no default is defined in the specification, you should make sure the corresponding argument is optional in your Python function as well, by assigning a default value:
def foo_get(optional_argument=None)
...
Missing arguments and kwargs¶
Connexion will inspect your function signature and only pass in the arguments that it defines. If an argument is defined in your specification, but not in your function, Connexion will ignore it.
If you do define a **kwargs
argument in your function signature, Connexion will pass in all
arguments, and the ones not explicitly defined in your signature will be collected in the
kwargs
argument.
Parameter Name Sanitation¶
The names of query and form parameters, as well as the name of the body parameter are sanitized by removing characters that are not allowed in Python symbols. I.e. all characters that are not letters, digits or the underscore are removed, and finally characters are removed from the front until a letter or an underscore is encountered. As an example:
>>> re.sub('^[^a-zA-Z_]+', '', re.sub('[^0-9a-zA-Z_]', '', '$top'))
'top'
Pythonic parameters¶
You can activate Pythonic parameters by setting the pythonic_params
option to True
on
either the application or the API:
from connexion import AsyncApp
app = AsyncApp(__name__, pythonic_params=True)
app.add_api("openapi.yaml", pythonic_params=True)
from connexion import FlaskApp
app = FlaskApp(__name__, pythonic_params=True)
app.add_api("openapi.yaml", pythonic_params=True):
from asgi_framework import App
from connexion import ConnexionMiddleware
app = App(__name__)
app = ConnexionMiddleware(app, pythonic_params=True)
app.add_api("openapi.yaml", pythonic_params=True)
This does two things:
CamelCase arguments are converted to snake_case
If the argument name matches a Python builtin, an underscore is appended.
When pythonic_params
is activated, the following specification:
paths:
/foo:
get:
operationId: api.foo_get
parameters:
- name: filter
description: Some filter.
in: query
schema:
type: string
required: true
- name: FilterOption
description: Some filter option.
in: query
schema:
type: string
paths:
/foo:
get:
operationId: api.foo_get
parameters:
- name: filter
description: Some filter.
in: query
type: string
required: true
- name: FilterOption
description: Some filter option.
in: query
type: string
Maps to the following Python function:
def foo_get(filter_, filter_option=None):
...
Type casting¶
Whenever possible Connexion will try to parse your argument values and cast them to the correct Python type:
OpenAPI Type |
Python Type |
---|---|
integer |
int |
string |
str |
number |
float |
boolean |
bool |
array |
list |
object |
dict |
null |
None |
Parameter serialization¶
Array and object parameters need to be serialized into lists and dicts.
The OpenAPI 3 specification defines the style and explode keywords which specify how these parameters should be serialized.
To handle these, Connexion provides the OpenAPIUriParser
class, which is enabled by
default when using an OpenAPI 3 spec.
Not all combinations of style and explode are supported yet. Please open an issue if you run into any problems.
The Swagger 2 specification defines the collectionFormat keyword to specify how these parameters should be serialized.
To handle this for you, Connexion provides the Swagger2URIParser
class, which is
enabled by default when using a Swagger 2 spec. It currently supports the pipes, csv,
and multi collection formats.
This parser adheres to the Swagger 2.0 spec, and will only join together multiple instance
of the same query parameter if the collectionFormat is set to multi. Query parameters
are parsed from left to right, so if a query parameter is defined twice, then the
right-most definition wins. For example, if you provided a URI with the query string
?letters=a,b,c&letters=d,e,f
and collectionFormat: csv
, then connexion will set
letters = ['d', 'e', 'f']
.
Connexion also provides two alternative parsers:
The
FirstValueURIParser
, which behaves like theSwagger2URIParser
, except that it prefers the first defined value.The
AlwaysMultiURIParser
, which behaves like theSwagger2URIParser
, except that it always joins together multiple instances of the same query parameter.
Context¶
Connexion can pass in some additional context. By default, this contains the following information:
{
"api_base_path": ... # The base path of the matched API
"operation_id": ... # The operation id of matched operation
"user": ... # User information from authentication
"token_info": ... # Token information from authentication
}
Third party or custom middleware might add additional fields to this.
To receive this in your function, you can either:
Request object¶
Connexion also exposes a Request
class which holds all the information about the incoming
request.
from connexion import request
View a detailed reference of the connexion.request
class
Warning
The asynchronous body arguments (body, form, files) might already be consumed by connexion. We recommend to let Connexion inject them into your view function as mentioned above.
- class connexion.lifecycle.ConnexionRequest(*args, uri_parser=None, **kwargs)¶
Implementation of the Connexion
_RequestInterface
representing an ASGI request.- _starlette_request
This class wraps a Starlette Request, and provides access to its attributes by proxy.
- property content_type¶
The content type included in the request headers.
- property context¶
The connexion context of the current request cycle.
- async files()¶
Files included in the request.
- async form()¶
Form data, including files.
- classmethod from_starlette_request(request: Request, uri_parser=None) ConnexionRequest ¶
- async get_body()¶
Get body based on the content type. This returns json data for json content types, form data for form content types, and bytes for all others. If the bytes data is empty,
None
is returned instead.
- async json()¶
Json data included in the request.
- property mimetype¶
The content type included in the request headers stripped from any optional character set encoding
- property path_params: Dict[str, Any]¶
Path parameters exposed as a dictionary
- property query_params¶
Query parameters exposed as a dictionary