diff --git a/README.rst b/README.rst index 17af23952..916677c56 100644 --- a/README.rst +++ b/README.rst @@ -264,6 +264,12 @@ In this example, Connexion automatically recognizes that your view function expects an argument named ``message`` and assigns the value of the endpoint parameter ``message`` to your view function. +.. note:: In the OpenAPI 3.x.x spec, the requestBody does not have a name. + By default it will be passed in as 'body'. You can optionally + provide the x-body-name parameter in your requestBody schema + to override the name of the parameter that will be passed to your + handler function. + .. warning:: When you define a parameter at your endpoint as *not* required, and this argument does not have default value in your Python view, you will get a "missing positional argument" exception whenever you call this endpoint @@ -278,7 +284,7 @@ do type casting to related Python native values. The current available type castings are: +--------------+-------------+ -| Swagger Type | Python Type | +| OpenAPI Type | Python Type | +==============+=============+ | integer | int | +--------------+-------------+ @@ -290,6 +296,8 @@ available type castings are: +--------------+-------------+ | array | list | +--------------+-------------+ +| null | None | ++--------------+-------------+ | object | dict | +--------------+-------------+ @@ -299,9 +307,9 @@ supports collection formats "pipes" and "csv". The default format is "csv". Connexion is opinionated about how the URI is parsed for ``array`` types. The default behavior for query parameters that have been defined multiple -times is to join them all together. For example, if you provide a URI with +times is to use the right-most value. For example, if you provide a URI with the the query string ``?letters=a,b,c&letters=d,e,f``, connexion will set -``letters = ['a', 'b', 'c', 'd', 'e', 'f']``. +``letters = ['d', 'e', 'f']``. You can override this behavior by specifying the URI parser in the app or api options. @@ -309,20 +317,25 @@ api options. .. code-block:: python from connexion.decorators.uri_parsing import Swagger2URIParser - options = {'uri_parsing_class': Swagger2URIParser} + options = {'uri_parsing_class': AlwaysMultiURIParser} app = connexion.App(__name__, specification_dir='swagger/', options=options) You can implement your own URI parsing behavior by inheriting from ``connextion.decorators.uri_parsing.AbstractURIParser``. -There are three URI parsers included with connection. +There are a handful of URI parsers included with connection. +----------------------+---------------------------------------------------------------------------+ -| AlwaysMultiURIParser | This parser is backwards compatible, and joins together multiple instances| -| (default) | of the same query parameter. | +| OpenAPIURIParser | This parser adheres to the OpenAPI 3.x.x spec, and uses the ``style`` | +| default: OpenAPI 3.0 | parameter. Query parameters are parsed from left to right, so if a query | +| | parameter is defined twice, then the right-most definition will take | +| | precedence. For example, if you provided a URI with the query string | +| | ``?letters=a,b,c&letters=d,e,f``, and ``style: simple``, then connexion | +| | will set ``letters = ['d', 'e', 'f']``. For additional information see | +| | `OpenAPI 3.0 Style Values`_. | +----------------------+---------------------------------------------------------------------------+ | Swagger2URIParser | This parser adheres to the Swagger 2.0 spec, and will only join together | -| | multiple instance of the same query parameter if the ``collectionFormat`` | +| default: OpenAPI 2.0 | 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 | @@ -334,6 +347,9 @@ There are three URI parsers included with connection. | | string ``?letters=a,b,c&letters=d,e,f`` and ``collectionFormat: csv`` | | | hen connexion will set ``letters = ['a', 'b', 'c']`` | +----------------------+---------------------------------------------------------------------------+ +| AlwaysMultiURIParser | This parser is backwards compatible with Connexion 1.x. It joins together | +| | multiple instances of the same query parameter. | ++----------------------+---------------------------------------------------------------------------+ Parameter validation @@ -351,18 +367,33 @@ to your application: API Versioning and basePath --------------------------- -You can also define a ``basePath`` on the top level of the API -specification. This is useful for versioned APIs. To serve the -previous endpoint from ``http://MYHOST/1.0/hello_world``, type: +Setting a base path is useful for versioned APIs. An example of +a base path would be the ``1.0`` in ``http://MYHOST/1.0/hello_world``. + +If you are using OpenAPI 3.x.x, you set your base URL path in the +servers block of the specification. You can either specify a full +URL, or just a relative path. + +.. code-block:: yaml + + servers: + - url: https://MYHOST/1.0 + description: full url example + - url: /1.0 + description: relative path example + + paths: + ... + +If you are using OpenAPI 2.0, you can define a ``basePath`` on the top level +of your OpenAPI 2.0 specification. .. code-block:: yaml basePath: /1.0 paths: - /hello_world: - post: - operationId: myapp.api.hello_world + ... If you don't want to include the base path in your specification, you can provide it when adding the API to your application: @@ -374,22 +405,27 @@ can provide it when adding the API to your application: Swagger JSON ------------ Connexion makes the OpenAPI/Swagger specification in JSON format -available from ``swagger.json`` in the base path of the API. +available from either ``swagger.json`` (for OpenAPI 2.0) or +``openapi.json`` (for OpenAPI 3.x.x) at the base path of the API. +For example, if your base path was ``1.0``, then your spec would be +available at ``/1.0/openapi.json``. -You can disable the Swagger JSON at the application level: +You can disable serving the spec JSON at the application level: .. code-block:: python - app = connexion.App(__name__, specification_dir='swagger/', - swagger_json=False) + options = {"serve_spec": False} + app = connexion.App(__name__, specification_dir='openapi/', + options=options) app.add_api('my_api.yaml') You can also disable it at the API level: .. code-block:: python - app = connexion.App(__name__, specification_dir='swagger/') - app.add_api('my_api.yaml', swagger_json=False) + options = {"serve_spec": False} + app = connexion.App(__name__, specification_dir='openapi/') + app.add_api('my_api.yaml', options=options) HTTPS Support ------------- @@ -428,7 +464,7 @@ You can disable the Swagger UI at the application level: .. code-block:: python - app = connexion.App(__name__, specification_dir='swagger/', + app = connexion.App(__name__, specification_dir='openapi/', options={"swagger_ui": False}) app.add_api('my_api.yaml') @@ -437,7 +473,7 @@ You can also disable it at the API level: .. code-block:: python - app = connexion.App(__name__, specification_dir='swagger/') + app = connexion.App(__name__, specification_dir='openapi/') app.add_api('my_api.yaml', options={"swagger_ui": False}) If necessary, you can explicitly specify the path to the directory with @@ -447,7 +483,7 @@ In order to do this, you should specify the following option: .. code-block:: python options = {'swagger_path': '/path/to/swagger_ui/'} - app = connexion.App(__name__, specification_dir='swagger/', options=options) + app = connexion.App(__name__, specification_dir='openapi/', options=options) If you wish to provide your own swagger-ui distro, note that connextion expects a jinja2 file called ``swagger_ui/index.j2`` in order to load the @@ -568,6 +604,7 @@ Unless required by applicable law or agreed to in writing, software distributed .. _Jinja2: http://jinja.pocoo.org/ .. _rfc6750: https://tools.ietf.org/html/rfc6750 .. _OpenAPI Specification: https://www.openapis.org/ +.. _OpenAPI 3.0 Style Values: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#style-values .. _Operation Object: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object .. _swager.spec.security_definition: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-definitions-object .. _swager.spec.security_requirement: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-requirement-object diff --git a/docs/cookbook.rst b/docs/cookbook.rst index ad482ee04..4019a1422 100644 --- a/docs/cookbook.rst +++ b/docs/cookbook.rst @@ -12,9 +12,9 @@ by the Connexion payload validation on request parameters and response payloads of your API. Let's say your API deals with Products and you want to define a field -`price_label` that have a "money" format value. You can create a format +`price_label` that has a "money" format value. You can create a format checker function and register that to be used to validate values of -"money" format. +the "money" format. Example of a possible schema of Product having an attribute with "money" format that would be defined in your OpenAPI specification: diff --git a/docs/index.rst b/docs/index.rst index 4b58eb037..e6e448cfa 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,8 +7,8 @@ Welcome to Connexion's documentation! ===================================== Connexion is a framework on top of Flask_ that automagically handles -HTTP requests based on `OpenAPI 2.0 Specification`_ (formerly known as -Swagger Spec) of your API described in `YAML format`_. Connexion +HTTP requests based on either the `OpenAPI 2.0 Specification`_ (formerly known +as Swagger Spec) or the `OpenAPI 3.0 Specification`_. Connexion allows you to write a Swagger specification and then maps the endpoints to your Python functions. This is what makes it unique from other tools that generate the specification based on your Python @@ -35,4 +35,4 @@ Contents: .. _Flask: http://flask.pocoo.org/ .. _OpenAPI 2.0 Specification: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md -.. _YAML format: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#format +.. _OpenAPI 3.0 Specification: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 12531ff26..7d5ace65e 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -14,19 +14,19 @@ In your command line, type this: .. code-block:: bash - $ pip install connexion + $ pip install connexion[swagger-ui] Running It ---------- -Put your API YAML inside a folder in the root path of your application (e.g ``swagger\``) and then do +Put your API YAML inside a folder in the root path of your application (e.g ``openapi\``) and then do .. code-block:: python import connexion - app = connexion.FlaskApp(__name__, specification_dir='swagger/') + app = connexion.FlaskApp(__name__, specification_dir='openapi/') app.add_api('my_api.yaml') app.run(port=8080) @@ -41,7 +41,7 @@ for each specific API in the `connexion.App#add_api` method: .. code-block:: python - app = connexion.FlaskApp(__name__, specification_dir='swagger/', + app = connexion.FlaskApp(__name__, specification_dir='openapi/', arguments={'global': 'global_value'}) app.add_api('my_api.yaml', arguments={'api_local': 'local_value'}) app.run(port=8080) @@ -58,8 +58,9 @@ You can disable the Swagger UI at the application level: .. code-block:: python - app = connexion.FlaskApp(__name__, specification_dir='swagger/', - swagger_ui=False) + options = {"swagger_ui": False} + app = connexion.FlaskApp(__name__, specification_dir='openapi/', + options=options) app.add_api('my_api.yaml') @@ -67,8 +68,9 @@ You can also disable it at the API level: .. code-block:: python - app = connexion.FlaskApp(__name__, specification_dir='swagger/') - app.add_api('my_api.yaml', swagger_ui=False) + options = {"swagger_ui": False} + app = connexion.FlaskApp(__name__, specification_dir='openapi/') + app.add_api('my_api.yaml', options=options) Server Backend -------------- @@ -79,7 +81,7 @@ to ``tornado`` or ``gevent``: import connexion - app = connexion.FlaskApp(__name__, port = 8080, specification_dir='swagger/', server='tornado') + app = connexion.FlaskApp(__name__, port = 8080, specification_dir='openapi/', server='tornado') Connexion has the ``aiohttp`` framework as server backend too: @@ -88,11 +90,9 @@ Connexion has the ``aiohttp`` framework as server backend too: import connexion - app = connexion.AioHttpApp(__name__, port = 8080, specification_dir='swagger/') + app = connexion.AioHttpApp(__name__, port = 8080, specification_dir='openapi/') .. _Jinja2: http://jinja.pocoo.org/ -.. _swagger.spec: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md -.. _swagger.spec.operation: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object .. _Tornado: http://www.tornadoweb.org/en/stable/ .. _gevent: http://www.gevent.org/ diff --git a/docs/request.rst b/docs/request.rst index d8ba56fb9..fbd01eb42 100644 --- a/docs/request.rst +++ b/docs/request.rst @@ -54,6 +54,12 @@ of the endpoint parameter `message` to your view function. Connexion will also use default values if they are provided. +.. note:: In the OpenAPI 3.x.x spec, the requestBody does not have a name. + By default it will be passed in as 'body'. You can optionally + provide the x-body-name parameter in your requestBody schema + to override the name of the parameter that will be passed to your + handler function. + .. warning:: Please note that when you have a parameter defined as *not* required at your endpoint and your Python view have a non-named argument, when you call this endpoint WITHOUT @@ -67,7 +73,7 @@ do type casting to related Python natives values. The current available type castings are: +--------------+-------------+ -| Swagger Type | Python Type | +| OpenAPI Type | Python Type | | | | +==============+=============+ | integer | int | @@ -80,18 +86,73 @@ available type castings are: +--------------+-------------+ | array | list | +--------------+-------------+ +| null | None | ++--------------+-------------+ | object | dict | +--------------+-------------+ -In the Swagger definition if the `array` type is used you can define the -`collectionFormat` that it should be recognized. Connexion currently +In the OpenAPI 2.0 specification, if the `array` type is used you can define the +`collectionFormat` used to deserialize the input. Connexion currently supports collection formats "pipes" and "csv". The default format is "csv". .. note:: For more details about `collectionFormat`'s please check the - official `Swagger/OpenAPI specification`_. + official `OpenAPI 2.0 Specification`_. + + +In the `OpenAPI 2.0 Specification`_ if you use the ``array`` type, +you can define the ``collectionFormat`` do set the deserialization behavior. +Connexion currently supports "pipes" and "csv" as collection formats. +The default format is "csv". + +Connexion is opinionated about how the URI is parsed for ``array`` types. +The default behavior for query parameters that have been defined multiple +times is to join them all together. For example, if you provide a URI with +the the query string ``?letters=a,b,c&letters=d,e,f``, connexion will set +``letters = ['a', 'b', 'c', 'd', 'e', 'f']``. + +You can override this behavior by specifying the URI parser in the app or +api options. + +.. code-block:: python + + from connexion.decorators.uri_parsing import Swagger2URIParser + options = {'uri_parsing_class': Swagger2URIParser} + app = connexion.App(__name__, specification_dir='swagger/', options=options) + +You can implement your own URI parsing behavior by inheriting from +``connextion.decorators.uri_parsing.AbstractURIParser``. + +There are a handful of URI parsers included with connection. + ++----------------------+---------------------------------------------------------------------------+ +| OpenAPIURIParser | This parser adheres to the OpenAPI 3.x.x spec, and uses the ``style`` | +| default: OpenAPI 3.0 | parameter. Query parameters are parsed from left to right, so if a query | +| | parameter is defined twice, then the right-most definition will take | +| | precedence. For example, if you provided a URI with the query string | +| | ``?letters=a,b,c&letters=d,e,f``, and ``style: simple``, then connexion | +| | will set ``letters = ['d', 'e', 'f']``. For additional information see | +| | `OpenAPI 3.0 Style Values`_. | ++----------------------+---------------------------------------------------------------------------+ +| Swagger2URIParser | This parser adheres to the Swagger 2.0 spec, and will only join together | +| default: OpenAPI 2.0 | 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']`` | ++----------------------+---------------------------------------------------------------------------+ +| FirstValueURIParser | This parser behaves like the Swagger2URIParser, except that it prefers | +| | the first defined value. For example, if you provided a URI with the query| +| | string ``?letters=a,b,c&letters=d,e,f`` and ``collectionFormat: csv`` | +| | hen connexion will set ``letters = ['a', 'b', 'c']`` | ++----------------------+---------------------------------------------------------------------------+ +| AlwaysMultiURIParser | This parser is backwards compatible with Connexion 1.x. It joins together | +| | multiple instances of the same query parameter. | ++----------------------+---------------------------------------------------------------------------+ + .. _jsonschema: https://pypi.python.org/pypi/jsonschema -.. _`Swagger/OpenAPI specification`: https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/2.0.md#fixed-fields-7 +.. _`OpenAPI 2.0 Specification`: https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/2.0.md#fixed-fields-7 Parameter validation ^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/routing.rst b/docs/routing.rst index 9d6b77aca..5e0baf82b 100644 --- a/docs/routing.rst +++ b/docs/routing.rst @@ -30,7 +30,10 @@ If you provided this path in your specification POST requests to x-swagger-router-controller: myapp.api operationId: hello_world -Keep in mind that Connexion follows how `HTTP methods work in Flask`_ and therefore HEAD requests will be handled by the ``operationId`` specified under GET in the specification. If both methods are supported, ``connexion.request.method`` can be used to determine which request was made. +Keep in mind that Connexion follows how `HTTP methods work in Flask`_ +and therefore HEAD requests will be handled by the ``operationId`` specified +under GET in the specification. If both methods are supported, +``connexion.request.method`` can be used to determine which request was made. Automatic Routing ----------------- @@ -120,21 +123,36 @@ requests to include forward slashes in the ``name`` url variable. API Versioning and basePath --------------------------- -You can also define a ``basePath`` on the top level of the API -specification. This is useful for versioned APIs. To serve the -previous endpoint from ``http://MYHOST/1.0/hello_world``, type: +Setting a base path is useful for versioned APIs. An example of +a base path would be the ``1.0`` in ``http://MYHOST/1.0/hello_world``. + +If you are using OpenAPI 3.x.x, you set your base URL path in the +servers block of the specification. You can either specify a full +URL, or just a relative path. + +.. code-block:: yaml + + servers: + - url: https://MYHOST/1.0 + description: full url example + - url: /1.0 + description: relative path example + + paths: + ... + +If you are using OpenAPI 2.0, you can define a ``basePath`` on the top level +of your OpenAPI 2.0 specification. .. code-block:: yaml basePath: /1.0 paths: - /hello_world: - post: - operationId: myapp.api.hello_world + ... If you don't want to include the base path in your specification, you -can just provide it when adding the API to your application: +can provide it when adding the API to your application: .. code-block:: python