OpenAPITools / OpenAPITools/openapi-generator

[BUG][PHP][PSR18] Invalid client generation when request body is json or xml

Open
#20,646 1 comment 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

I have generated PHP PSR-18 clients and models from an external API. The OpenAPI spec has a POST endpoint which supports json and xml format in the request body. In this case the generated code of the create*Request method looks weird. It produces this passage:

$headers = $this->headerSelector->selectHeaders(
    [],
    'application/jsonapplication/xml',
    $multipart
);

which leads to an error, because it uses application/jsonapplication/xml as Content-Type, which is obviously wrong, and it fails with the following

TypeError: GuzzleHttp\Psr7\Request::withBody(): Argument #1 ($body) must be of type Psr\Http\Message\StreamInterface, Test\Api\Models\CreateUserTaskRequest given, called in /srv/htdocs/tests/openapi-generator/generated/lib/Clients/DefaultClient.php on line 413

openapi-generator version

generator cli version: 7.11.0

OpenAPI declaration file content or url

The API is not public, so I have taken the specific endpoint and anonymized the spec. But the issue is reproducible with it.

openapi: 3.0.1
info: {title: Test API, description: test description, version: 1.8.8}
servers: [{url: https://example.com/api}]
paths:
    /usertasks:
        post:
            summary: Create a task
            description: "Create a new task for a user"
            operationId: createUserTask
            requestBody:
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateUserTaskRequest'
                    application/xml:
                        schema:
                            $ref: '#/components/schemas/CreateUserTaskRequest'
                required: true
            responses:
                "204":
                    $ref: '#/components/responses/NoContent'
                "400":
                    $ref: '#/components/responses/BadRequest'
components:
    schemas:
        CreateUserTaskRequest:
            required:
                - channel
                - subject
                - text
                - type
            type: object
            properties:
                subject:
                    type: string
                    description: Title
                text:
                    type: string
                    description: Description
                channel:
                    description: Channel
                    $ref: '#/components/schemas/UserTaskChannel'
                type:
                    type: string
                    description: Task type
            description: Create task
            xml:
                name: userTaskRequest
        UserTaskChannel:
            type: string
            description: Channel
            enum: [BACKOFFICE, LOGISTICS, TRADING]
    responses:
        BadRequest:
            description: Invaid request, e.g. syntax error, exceeding limit
        NoContent:
            description: "Request successfull, but no response"
Generation Details

I have used this snippet for the generation:

npx @openapitools/openapi-generator-cli@2.15.3 generate \
        -o generated \
        -i openapi.yaml \
        --api-name-suffix Client \
        -g php \
        --additional-properties 'apiPackage=Clients' \
        --additional-properties 'modelPackage=Models' \
        --additional-properties 'invokerPackage=Test\\Api' \
        --additional-properties 'library=psr-18'
Steps to reproduce
  1. Generate the code with the snippet above.
  2. Open the file ./generated/test/Api/DefaultClientTest.php
  3. Insert the following code into the prepared testCreateUserTask() method:
        $client = new DefaultClient();

        $data = new CreateUserTaskRequest([
            'subject' => 'test',
            'text' => 'test',
            'channel' => 'BACKOFFICE',
            'type' => 'test',
        ]);
        $client->createUserTask($data);
  1. do a composer install
  2. run vendor/bin/phpunit

Then you should get the error mentioned above.

Related issues/PRs

I did not found any

Suggest a fix

When I comment out these lines in the spec:

                    application/xml:
                        schema:
                            $ref: '#/components/schemas/CreateUserTaskRequest'

The correct code is generated. So my guess is that the generator cannot handle different media types in the request body. Maybe in such cases there should be a further parameter in the client method (in this case createUserTask()) to pass the desired content-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 issue with the supplied OpenAPI YAML and the npx @openapitools/openapi-generator-cli@2.15.3 command, then inspect the generated DefaultClient.php and DefaultClientTest.php. Compare generation with both media types against JSON alone, and run composer install followed by vendor/bin/phpunit; done means the generated PSR-18 client handles the request body and content type correctly for JSON and XML.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.