Openapispex does not send data in POST body

I’m getting to know OpenApiSpex. I try to create a function on a REST API with two parameters and I’d like to pass the parameters in the body of the POST requests (I think this is how this stuff is usually used). So far I’ve came up with this:

  def login_operation() do
    %Operation{
      tags: ["users"],
      summary: "Logs in the user",
      description: "Log in the user",
      operationId: "LoginController.login",
      parameters: [
        Operation.parameter(:username, :path, :string, "User Name",
          example: "test",
          required: true
        ),
        Operation.parameter(:number, :path, :integer, "Some number",
          example: 12,
          required: true
        )
      ],
      responses: %{
        200 => Operation.response("User", "application/json", UserWeb.LoginResponse)
      }
    }
  end

My problem is that on the local Swagger UI (http://localhost:4000/swaggerui#/users/LoginController.login) if I press “Try it out”, then “execute”, the “username” and “number” are not added to the body. I tried to use “:query” for location (instead of “:path”), but in that case the parameters were included in the URI. How should I configure the parameters that the Swagger UI put them into the body?

1 Like

I only found a workaround: instead of using parameters in the Operation map, I created a whole new schema(?) and use that in the requestBody field of the Operation map. So I have this new module:

defmodule MerlinWeb.LoginParameter do
require OpenApiSpex

  OpenApiSpex.schema(%{
    title: "LoginParameter",
    description: "Input for login",
    type: :object,
    properties: %{
      username: %OpenApiSpex.Schema{type: :string, description: "name of the user"},
      some_number: %OpenApiSpex.Schema{type: :integer, description: "some number"}
    },
    required: [:username, :some_number],
    example: %{
        "username" => "some user",
        "some_number" => "12"
    }
  })
end

and in the above example instead of the parameters: part I have this:

      parameters: [],
      requestBody: Operation.request_body("Login params description", "application/json",
          MerlinWeb.LoginParameter,
          required: true),

It means that on the Swagger UI I don’t have a separate text field for all parameters anymore (username, number in the above examples), but one single text area for the JSON input. Doesn’t look that good, but works.

2 Likes

Your solution is correct. Swagger 3 separates the requestBody from the parameters, which allows for defining multiple schemas for different content types.

To get a better editing experience, some customisation of swagger-ui might be required. I found this comment which mentions using react-jsonschema-form to edit the json body.

2 Likes