swagger-typescript-api icon indicating copy to clipboard operation
swagger-typescript-api copied to clipboard

Response `format` - global default or override ?

Open Liwoj opened this issue 3 years ago • 1 comments

Hi

First thanks for great generator - really like it! Great work!

In release 8.0.0 there was this commit which introduced feature "Allow to set global response type format through HttpClient constructor"

It was implemented both in Axios and Fetch clients as const responseFormat = format && requestParams.format; which works more like a global override (format passed into the constructor takes precedence over format passed into request)

It was later changed to const responseFormat = format || requestParams.format; with this commit so it works more like a global default. But the change was made only in Fetch template - in Axios it is still implemented as global override...

As the current Fetch template behavior makes more sense, I guess it is actually a bug in the Axios template.

And that brings me to other part of the question. I do not want the Axios (or underlying XmlHttpRequest) to run a JSON.parse on my responses. Reason is I'm using custom JSON.parse reviver function to parse all strings in the correct format directly to Date. So code generated with current version of swagger-typescript-api when used with current version of Axios (0.21.1) and passing format: 'text' into Api constructor works just fine. But if the problem mentioned above will be fixed and format: 'json' generated for my API routes starts overriding global default, it will break because format is passed into Axios param responseType and that is passed into responseType of XmlHttpRequest - as a result Axios starts to return JS objets parsed from JSON instead of just text...

This might not be an issue in the end thanks to this recent change in Axios (not yet released) but I'm not sure (Axios development is a bit chaotic for me to follow) what is plan for the future (see this change in 1.0.0 branch)

So the question is, what is the easiest way to fix this ? Override the generation of format: 'json' for my routes ? Or something else ?

Thanks!

Liwoj avatar May 04 '21 13:05 Liwoj

Hi!

I have a problem that is, as I guess, related:

Axios template generates a request function as followed:

  public request = async <T = any, _E = any>({
    secure,
    path,
    type,
    query,
    format,
    body,
    ...params
  }: FullRequestParams): Promise<AxiosResponse<T>> => {
    const secureParams =
      ((typeof secure === "boolean" ? secure : this.secure) &&
        this.securityWorker &&
        (await this.securityWorker(this.securityData))) ||
      {};
    const requestParams = this.mergeRequestParams(params, secureParams);
    const responseFormat = (format && this.format) || void 0;
...

the problem is, that, even if you pass format (e.g. "stream") to your request, it will never arrive in responseFormat hence "stream" && null is always null

I think this should be changed to: const responseFormat = format || this.format

This leads to the following problem, because you cannot pass { format: "stream" } to a request, e.g. for a proxied download:

this.backend.v1.downloadFile(id, { format: "stream"})
            .then((res: any) => res.data.pipe(response))
// cannot read property pipe of undefined

while this works:

this.backend.instance.get("/v1/Downloads/" + id, { responseType: "stream"})
     .then(res => res.data.pipe(response))

ndrsg avatar Jul 21 '21 07:07 ndrsg