swaggerflask-sqlalchemyopenapiconnexion

OpenAPI v3 / Swagger - calling a function and sending json dictionary to it


I'm trying to use OpenAPI/Swagger to run an endpoint capable of consuming a json dictionary, sending to a function and getting a response.

I'm using operationId to refer to the function that I want to call, but can't work out how to send the dictionary that's received by the endpoint.

controllers.get_options is called, but no parameters are sent to it with my current approach.

I think I'm missing something obvious, but it's not apparent!

I would call the endpoint like this:

curl -X 'POST' \
  'http://localhost:8080/getoptions' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "product_area": "Main",
  "product_type": "New"
}'

This is the openapi config file (./openapi.yaml)

EDIT: adding x-body-name: DiscussionResult below solved the issue as per Helen's comment

openapi: 3.0.0
info:
  title: Test
  version: '1.0'
paths:
  /getoptions:
    post:
      description: Return product options from product type and area
      operationId: controllers.get_options
      requestBody:
        required: true
        content:
          application/json:
            x-body-name: DiscussionResult
            schema:
              $ref: '#/components/schemas/DiscussionResult'
      responses:
        200:
          description: "success"

components:
  schemas:
    DiscussionResult:
      type: object
      discriminator:
        propertyName: product_type
      properties:
        product_type:
          type: string
          example: "New"
        product_area:
          type: string
          example: "Main"


I'm running it using connexion as shown here:

main.py

import connexion
import logging

def create_app():
    logging.basicConfig(level=logging.DEBUG)
    connex_app = connexion.FlaskApp(__name__, specification_dir="./openapi/")
    connex_app.add_api("./openapi.yaml", resolver_error=501)
    return connex_app


if __name__ == "__main__":
    app = create_app()
    app.run(host="0.0.0.0", port=8080)

requirements.txt

connexion[swagger-ui]
connexion>=2.2.0
python-jose[cryptography]
six>=1.9
Flask>=0.10.1
sqlathanor

and this is the function that I want to call

def get_options(DiscussionResult):
    msg = "{} {}".format(DiscussionResult['product_area'], DiscussionResult['product_type'])
    return jsonify(message=msg), 200

Solution

  • Connexion docs on Request Handling include the following 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.

    Looks like you need to add x-body-name: DiscussionResult to the DiscussionResult schema that is used in the requestBody:

    components:
      schemas:
        DiscussionResult:
          x-body-name: DiscussionResult   # <---------
          type: object
          ...
    

    or

          requestBody:
            required: true
            content:
              application/json:
                schema:
                  x-body-name: DiscussionResult   # <---------
                  $ref: '#/components/schemas/DiscussionResult'