OpenAPITools / OpenAPITools/openapi-generator

[BUG][ELIXIR] Typespecs do not match function return types for empty response body

Open
#17,553 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

For endpoints returning empty responses, the Elixir client generator produces typespecs which do not match the function return type.

An empty 'OK' response has generated typespec as {:ok, nil}, whereas the value returned by the generated client function is actually {:ok, %Tesla.Env{}}.

The typespec is determined here, whilst the return type is indirectly determined here. (The {response_code, false} tuple is eventually forwarded to this function, which results in {:ok, %Tesla.Env{}}).

openapi-generator version

7.0.1. This is not a regression.

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: Spec
  version: 1.0.0
servers:
  - url: https://example.com
paths:
  /pet/{petId}:
    delete:
      tags:
        - pet
      summary: Deletes a pet
      description: delete a pet
      operationId: deletePet
      parameters:
        - name: petId
          in: path
          description: Pet id to delete
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '204':
          description: Pet deleted successfully
        '400':
          description: Invalid pet value
Generation Details

Taking the spec above as openapi-spec.yaml:

openapi-generator-cli generate -i openapi-spec.yaml -g elixir

This generates a Spec.Api.Pet.delete_pet/3 function:

  @doc """
  Deletes a pet
  delete a pet

  ### Parameters

  - `connection` (Spec.Connection): Connection to server
  - `pet_id` (integer()): Pet id to delete
  - `opts` (keyword): Optional parameters

  ### Returns

  - `{:ok, nil}` on success
  - `{:error, Tesla.Env.t}` on failure
  """
  @spec delete_pet(Tesla.Env.client, integer(), keyword()) :: {:ok, nil} | {:error, Tesla.Env.t}
  def delete_pet(connection, pet_id, _opts \\ []) do
    request =
      %{}
      |> method(:delete)
      |> url("/pet/#{pet_id}")
      |> Enum.into([])

    connection
    |> Connection.request(request)
    |> evaluate_response([
      {204, false},
      {400, false}
    ])
  end

The typespec and docstring give {:ok, nil} as the return type on success, but evaluate_response will actually return {:ok, Tesla.Env.t()}.

Steps to reproduce

Run the generate as above and observe the generated code.

Related issues/PRs

I couldn't find any related issues.

Suggest a fix

The fix depends on what we think is 'sensible' to return in the case of an empty response body. I see two options:

  1. The correct result type is {:ok, nil}. We need to modify the decode helper in RequestBuilder to return nil. (This will need some special-casing as the false argument to decode means 'do not try to decode the response'; we want the semantics for the empty-response-body case to be 'decode the empty response body as nil, and leave other response types as they are.)
  2. The correct result type is {:ok, Tesla.Env.t()}. We need to modify the typespec generation to return this type.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the generated Elixir client from the provided OpenAPI YAML, then inspect ElixirClientCodegen.java around lines 687-688 and 817-818 and request_builder.ex.mustache around line 186. Determine which empty-response result is intended, make the generated typespec and function behavior agree, and verify the generated delete_pet function and documentation report the same success type.

Written by the indexing model from the issue text.

Assessment

Tech stack
elixir, java, openapi
Domain
backend-api-design, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.