Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG][typescript-node] The same response type deserialized for all HTTP statuses #2924

Closed
5 of 6 tasks
quezak opened this issue May 17, 2019 · 4 comments · Fixed by #10940
Closed
5 of 6 tasks

[BUG][typescript-node] The same response type deserialized for all HTTP statuses #2924

quezak opened this issue May 17, 2019 · 4 comments · Fixed by #10940

Comments

@quezak
Copy link

quezak commented May 17, 2019

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • What's the version of OpenAPI Generator used?
  • Have you search for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Bounty to sponsor the fix (example)
Description

Use case:

  • on HTTP 200 OK, API returns a TestResponse
  • on any (or specific) errors, API returns an ErrorResponse

Bug: the client generated with typescript-node always tries to deserialize the successful type only. Because the ObjectDeserializer only deserializes known fields, the generated code rejects with an empty body, and with no access to the actual error body.

Here's the offending code snippet generated (it's the same for all paths in spec):

        return new Promise<{ response: http.IncomingMessage; body: TestResponse;  }>((resolve, reject) => {
            localVarRequest(localVarRequestOptions, (error, response, body) => {
                if (error) {
                    reject(error);
                } else {
                    // This will deserialize `{}` for an `ErrorResponse`!
                    body = ObjectSerializer.deserialize(body, "TestResponse");
                    if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) {
                        resolve({ response: response, body: body });
                    } else {
                        reject({ response: response, body: body });
                    }
                }
            });
        });

Fix proposition at the bottom.

openapi-generator version

I think all, I've tested:

  • 4.0.0
  • 4.1.0-20190515.034101-2
  • 5.0.0-20190515.034058-2
OpenAPI declaration file content or url

full example on gist

The most important part -- I've tried the second response with default, 500 and 5XX keys, all yielding the same result.

                "responses": {
                    "200": {
                        "description": "Successful operation",
                        "schema": { "$ref": "#/definitions/TestResponse" }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": { "$ref": "#/definitions/ErrorResponse" }
                    }
                }
Command line used for generation

java -jar ~/pkg/openapi-generator-cli-5.0.0-20190515.034058-2.jar generate -i test.json -g typescript-node -D supportsES6=true

Steps to reproduce
  1. Generate the clients
  2. Inspect the generated code :)
Suggest a fix

The body should be deserialized to a proper type, depending on the HTTP status code. For example:

        return new Promise<{ response: http.IncomingMessage; body: TestResponse;  }>((resolve, reject) => {
            localVarRequest(localVarRequestOptions, (error, response, rawBody) => {
                if (error) {
                    reject(error);
                } else {
                    if (response.statusCode && response.statusCode === 200) {
                        const body = ObjectSerializer.deserialize(body, "TestResponse");
                        resolve({ response, body });
                    // Note 1: If I specified a response for "5XX" status, this should be also checked, but here I used "default"
                    // else if (response.statusCode && response.statusCode >= 500 && response.statusCode <= 599) {
                    } else {
                        const body = ObjectSerializer.deserialize(body, "ErrorResponse");
                        reject({ response, body });
                    }
                    // Note 2: If the spec doesn't have a "default" response key, the response type is not known,
                    // then it probably should `reject({ response, body: rawBody })`
                }
            });
        });
@auto-labeler
Copy link

auto-labeler bot commented May 17, 2019

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@quezak quezak changed the title [BUG][typescript-node] The same response type deserialized for all states [BUG][typescript-node] The same response type deserialized for all HTTP states May 17, 2019
@quezak quezak changed the title [BUG][typescript-node] The same response type deserialized for all HTTP states [BUG][typescript-node] The same response type deserialized for all HTTP statuses May 17, 2019
@quezak
Copy link
Author

quezak commented Feb 14, 2020

Just a quick update, in the latest 5.0.0 snapshots the reject variant throws an HttpError instead of a plain object, but still with the same body parameter -- which will be empty if the error response type is different (which is true 99% of the time).

Posting this just FYI, I know the typescript generators are under a rewrite, waiting patiently for them to be done 😃

            return new Promise<{ response: http.IncomingMessage; body: TestResponse;  }>((resolve, reject) => {
                localVarRequest(localVarRequestOptions, (error, response, body) => {
                    if (error) {
                        reject(error);
                    } else {
                        body = ObjectSerializer.deserialize(body, "TestResponse");
                        if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) {
                            resolve({ response: response, body: body });
                        } else {
                            reject(new HttpError(response, body, response.statusCode));
                        }
                    }
                });
            });

@jaydeep987
Copy link

jaydeep987 commented Oct 7, 2021

Not a solution but just kind of thing I found with ObjectSerializer. (typescript only generator)
I like framework agnostic approach. But in js world, I think tightly bound code is bit problematic. Like the pure typescript generator produces models and response is deserialized to match model (which as that attributemap).

ObjectSerializer.deserialize(ObjectSerializer.parse(await response.body.text(), contentType), "MyModel", "")

There are higher chances that openapi schema file is not up to date, and I am not gonna wait for the backend to update their spec. (sometimes it is third party company). And so, the model also wont have attributes which may be present in response.
So I would like approach which definitely match response to attribute map, but also provide additional response as props like accessible.
Using typescrip-xxx (like typescript-fetch etc) is not solution, its either not framework agnostic or none of them supports authorization.

dever4eg added a commit to dever4eg/openapi-generator that referenced this issue Nov 23, 2021
I've found this bug in @kubernetes/client-node npm package.

By the way, Here is the issue OpenAPITools#2924
@dever4eg
Copy link
Contributor

dever4eg commented Nov 23, 2021

Here is the workaround

const deserialize = ObjectSerializer.deserialize;
ObjectSerializer.deserialize = (data: any, type: string) => {
  if (data?.status === 'Failure') {
    return data;
  }
  eturn deserialize(data, type);
}

macjohnny pushed a commit that referenced this issue Nov 24, 2021
* Fixed http errors deserialization

I've found this bug in @kubernetes/client-node npm package.

By the way, Here is the issue #2924

* Update typescript-node samples with a fix of error handling

* Update samples version

Co-authored-by: Bogdan Onischenko <bogdan.onischenko@nixsolutions.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants