OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.31k stars 6.45k forks source link

[BUG][PHP] Code unreachable for responses other than 2xx and bad return types #7788

Open deluxetom opened 3 years ago

deluxetom commented 3 years ago
Description

The generated PHP code (case 400:) is unreachable when a response with HTTP code 400 is defined. It adds that return type to the PHPdoc but it's never returned as the RequestException is caught for anything different than a 2xx. Tools like Psalm will expect a return type that will never be returned.

/**
 * Operation registerWithHttpInfo
 *
 * Add a User
 *
 * @param  \Eplay\ApiClient\Model\UserForm $userForm User form (required)
 *
 * @throws \Eplay\ApiClient\ApiException on non-2xx response
 * @throws \InvalidArgumentException
 * @return array of \Eplay\ApiClient\Model\User|\Eplay\ApiClient\Model\FormValidationErrorResponse, HTTP status code, HTTP response headers (array of strings)
 */
public function registerWithHttpInfo($userForm)
{
    $request = $this->registerRequest($userForm);

    try {
        $options = $this->createHttpClientOption();
        try {
            $response = $this->client->send($request, $options);
        } catch (RequestException $e) {
            throw new ApiException(
                "[{$e->getCode()}] {$e->getMessage()}",
                $e->getCode(),
                $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                $e->getResponse() ? (string) $e->getResponse()->getBody() : null
            );
        }

        $statusCode = $response->getStatusCode();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                $response->getBody()
            );
        }

        $responseBody = $response->getBody();
        switch($statusCode) {
            case 200:
                if ('\Eplay\ApiClient\Model\User' === '\SplFileObject') {
                    $content = $responseBody; //stream goes to serializer
                } else {
                    $content = (string) $responseBody;
                }

                return [
                    ObjectSerializer::deserialize($content, '\Eplay\ApiClient\Model\User', []),
                    $response->getStatusCode(),
                    $response->getHeaders()
                ];
            case 400:
                if ('\Eplay\ApiClient\Model\FormValidationErrorResponse' === '\SplFileObject') {
                    $content = $responseBody; //stream goes to serializer
                } else {
                    $content = (string) $responseBody;
                }

                return [
                    ObjectSerializer::deserialize($content, '\Eplay\ApiClient\Model\FormValidationErrorResponse', []),
                    $response->getStatusCode(),
                    $response->getHeaders()
                ];
        }
...
}
openapi-generator version

v5.0.0-beta2

OpenAPI declaration file content or url
"/user/{user}": {
    "put": {
        "tags": [
            "user"
        ],
        "summary": "Edit a user",
        "description": "Edit a user",
        "operationId": "edit",
        "parameters": [
            {
                "name": "user",
                "in": "path",
                "description": "User ID",
                "required": true,
                "schema": {
                    "type": "string"
                }
            }
        ],
        "requestBody": {
            "description": "User update form",
            "required": true,
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/UserUpdateForm"
                    }
                }
            }
        },
        "responses": {
            "200": {
                "description": "Returns the user on success",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/User"
                        }
                    }
                }
            },
            "400": {
                "description": "Returns a 400 on validation failure",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/FormValidationErrorResponse"
                        }
                    }
                }
            }
        }
    },
},
Generation Details
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli:v5.0.0-beta2 generate \
            -i /local/api.spec.json \
            -g php \
            -c /local/terraform/openapi-clients/php/config.json \
            -o /local/tmp-client \
            --skip-validate-spec

config.json

{
    "invokerPackage": "Eplay\\ApiClient",
    "srcBasePath": "lib",
    "phpLegacySupport": "false",
    "variableNamingConvention": "camelCase"
}
Steps to reproduce

Generate the client with a model defined for a response different than 2xx

Related issues/PRs
Suggest a fix
archadamaster commented 2 years ago

Any update on this? There is no way to catch correct response other that 2xx

Current solution is awkward

catch (\Throwable $ex)
        {
            $errorObject = $ex->getResponseObject();
            if ($errorObject instanceof \TTPrices\OpenAPI\Account\Model\JsonApiError) {
                die($errorObject->getErrors()[0]);
            } 
kruegge82 commented 2 weeks ago

same problem, have commented out:

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                $response->getBody()
            );
        }

and also on $apiInstance put off http errors off: $apiInstance = new OPENApi\Client\Api\Class(new GuzzleHttp\Client(['http_errors'=>false]), $config);