hey-api / openapi-ts

✨ Turn your OpenAPI specification into a beautiful TypeScript client
https://heyapi.vercel.app
Other
969 stars 77 forks source link

Get response headers #766

Open mfinelli opened 1 month ago

mfinelli commented 1 month ago

Description

I'm opening an issue for the discussion here: https://github.com/hey-api/openapi-ts/discussions/371#discussion-6495764

My API spec includes some responses where there is both a (JSON) body as well as some extra information in some of the response headers which is useful to me on the client side. I'm reading the code and it seems that the fetch client only returns the data or an error but not the raw response so that I can pull out the headers manually. Is there some other way to access the raw response and/or response headers?

But it would be even better IMO if the client exposed any headers listed in the openapi spec (so that we can get proper types for them etc).

mrlubos commented 1 month ago

You can do this with the new Fetch API client, is that an option for you?

mfinelli commented 1 month ago

I'm using the new fetch api client (I think, I have client: "@hey-api/client-fetch" set in my openapi-ts.config.ts file), but the examples on the page all seem to work with the request headers, but I need access to the response headers. The generated client functions all return types like ...get<GetSomeResponse, GetSomeError> so it's not clear how I can get at the raw response.

mrlubos commented 1 month ago

@mfinelli the new Fetch API client returns 4 things: data, error, request, and response. Response is the raw object containing your headers. They won't be properly typed, but they are there

mfinelli commented 1 month ago

Ok, I see how it works now. For anyone else finding this issue I'm able to get the raw response like so:

const { data, error, response } = await yourClientFunction(...);

Then you can pull individual headers like this

response.headers.get("X-Your-Header");

@mrlubos I still think it would be a good idea if the generated client could read the headers from the openapi spec and expose them in a more standard way along with the proper types, but if you disagree then you can close this issue as resolved. Thanks for your help!

mrlubos commented 1 month ago

@mfinelli It depends on how you imagine the standardised way. My understanding is that getting headers from response is straightforward, minus the missing type support. I'd argue that the more stuff you put in the data field (if that was your proposal), the closer it gets to being a typed response object

mfinelli commented 1 month ago

I'm not sure that I'd like it in the data object unless the data object had two keys body and headers. My usecase is to add extra information on the server side into some custom headers (e.g., pagination details) without affecting the response body itself which corresponds directly to a model that exists in the database and in the openapi spec (e.g., GET /category returns an array of Category objects, I wouldn't want to try and stuff the pagination information in there too)

mrlubos commented 1 month ago

If you have any ideas around implementation feel free to propose, I didn't spend too much time thinking about this feature

bielas commented 1 month ago

can you tell me how to get headers from that kind of code using v.0.49 of "@hey-api/openapi-ts"?

image
mrlubos commented 1 month ago

@bielas looks like you're using Angular with the new Fetch API client? See my comment in https://github.com/hey-api/openapi-ts/issues/667#issuecomment-2233629443. I didn't prioritise this use case yet, sorry!

bielas commented 1 month ago

@mrlubos nope, I am using react and default client

mrlubos commented 1 month ago

I am confused then, parseAs is available only in the new Fetch API client?

bielas commented 1 month ago

@mrlubos I am using client version 0.1.3 and hey api version 0.49. Seems that is is possible...

bielas commented 1 month ago

How then I should proceed?

bielas commented 1 month ago

If you provide me any other solution I can stop using parseAs and go with the other one

mrlubos commented 1 month ago

@bielas here's how you can obtain response headers https://stackblitz.com/edit/hey-api-client-fetch-example?file=src%2FApp.tsx%3AL106

bielas commented 1 month ago

how this is possible to work as open api generated code looks like:

export const downloadSubscription = (options: Options<DownloadSubscriptionData>) => {
    return (options?.client ?? client).get<DownloadSubscriptionResponse, DownloadSubscriptionError>(
        {
            ...options,
            url: '/v1/self/trainer/subscription/{subscriptionId}/invoice'
        }
    );
};

export type DownloadSubscriptionResponse = Blob | File;

i am not able to extract it like you do here:

const { data, error, response } = await getPetById({

mrlubos commented 1 month ago

@bielas please create a StackBlitz example, hard to tell from the code, it looks fine to me

bielas commented 1 month ago

@mrlubos I hope you will get my point: https://stackblitz.com/edit/vitejs-vite-kemti5?file=src%2FApp.tsx

mrlubos commented 1 month ago

@bielas I can't reproduce it with that. However, I see you're accessing data in the tap() function. data will not contain the headers, you need the raw response object for that