cyclosproject / ng-openapi-gen

An OpenAPI 3.0 codegen for Angular
MIT License
397 stars 132 forks source link

Generated service methods with type of Observable<void> cause odd behaviour when trying to interact with error responses from the same endpoint. #153

Closed Jake-Thomas-Hall closed 3 years ago

Jake-Thomas-Hall commented 3 years ago

Hey there,

So I have this endpoint, that is defined like so in the openapi document:

"/api/AccountOrganisation": {
  "patch": {
    "tags": [
      "AccountOrganisation"
    ],
    "operationId": "AccountOrganisation_Patch",
    "requestBody": {
      "x-name": "command",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/UpdateAccountOrganisationCommand"
          }
        }
      },
      "required": true,
      "x-position": 1
    },
    "responses": {
      "200": {
        "description": ""
      },
      "400": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "404": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "500": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      }
    },
    "security": [
      {
        "oauth2": []
      }
    ]
  }
},

It is simply an endpoint that takes an object, updates it in the db/backend and then returns a 200 response if it succeeds.

This used to work fine in ng-swagger-gen, I obviously didn't interact with the 200 response as it didn't return an object, but I could still interact with the error responses which do return objects.

However, now due to how these types of endpoints are generated as Observable<void> it causes odd casting behaviour when I try to interact with the error response, for example:

this.accountOrganisationService.accountOrganisationPatch({ body: updateLiableParty }).subscribe({
    next: () => {
      // Perform some actions here on success
    },
    error: (error: HttpErrorResponse) => {
      // Here is where the problem occurs, the error, which is supposed to be an object, is in fact a string so trying to access any properties of it like normal fails.
      const problemDetails: ProblemDetails = error.error;
    }
});

Is there any solution to this? I would really rather not make all our patch endpoints have to return some dummy response to get around this odd void conversion issue.

For now I'll just use JSON.parse to convert the string to an object, but I would really prefer not needing to do this either, especially when it has the capability to return an object normally.

luisfpg commented 3 years ago

I see no obvious way to fix this, unfortunately. We work with services that, for example, return a string in the success response, but the errors are always JSON. So our error handler will check whether the HttpErrorResponse.error field is a string, and in that case, use JSON.parse, just like you're doing. See https://github.com/cyclosproject/cyclos4-ui/blob/c20efee8bb425fd47d4b99cfcd0a0380347bf52c/src/app/core/error-handler.service.ts#L60

Jake-Thomas-Hall commented 3 years ago

I see no obvious way to fix this, unfortunately. We work with services that, for example, return a string in the success response, but the errors are always JSON. So our error handler will check whether the HttpErrorResponse.error field is a string, and in that case, use JSON.parse, just like you're doing. See https://github.com/cyclosproject/cyclos4-ui/blob/c20efee8bb425fd47d4b99cfcd0a0380347bf52c/src/app/core/error-handler.service.ts#L60

Ok, that's fair enough, like you suggested, we've just been parsing the responses if they are strings and are supposed to be objects.