ecyrbe/zodios

Access raw axios Response object / headers from response?

ajwootto opened this issue · 19 comments

Hi, sorry if I missed this in the documentation. Is there a way to access the raw Response object from Axios from an apiClient request on the client side? Specifically I want to be able to inspect the headers of the response in addition to the response body. I only see a way to get the actual body returned:

  // how to get access to raw response here?
  const variable = await zodiosClient.get(
    `/v1/projects/:project/variables/:key`,
    {
      params: { project: projectId, key: id },
    },
  )
  return variable
ecyrbe commented

Hello, you can, with zodios plugins or axios interceptor.
if you need to actually extract headers for data or behaviour purpose, plugins may not be enough.

However, in next planned v11 version zodios will return data, error and headers in inlined object like this :

const { data, error, status, headers } = await zodiosClient.get(
    `/v1/projects/:project/variables/:key`,
    {
      params: { project: projectId, key: id },
    },
  )

yeah I need the headers for behaviour purposes, specifically I have a paginated API I'm hitting where the total count of entities is represented as a header value.

The v11 signature looks like it will work for me

ecyrbe commented

Ok, i expect to be able to release a new beta of v11 with this feature this week-end if you want to try it early

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was the header feature added to the v11 release? I have the same use case as the poster. A paginated API I'm using returns the total number of records as a header value.

ecyrbe commented

@shepherdjerred i'm sorry, i'm revamping the whole v11 beta state with a lot of breaking changes at the moment with a new api definition shape ongoing here : https://github.com/ts-api-spec/typematic
so i can't recommand you going to v11 at the moment. would mean a lot of refactoring for you afterwards.
so no solution at the moment.

No worries! Thanks for being so prompt, and for making this library! It has really helped me integrate Zod into my application.

As a workaround, I wrote a quick plugin for this:

export const SizeHeaderPlugin: ZodiosPlugin = {
  name: "SizeHeaderPlugin",
  response: (
    _api: ZodiosEndpointDefinitions,
    _config: ReadonlyDeep<AnyZodiosRequestOptions>,
    response: AxiosResponse
  ): Promise<AxiosResponse> => {
    if (response.headers[SIZE_HEADER]) {
      return Promise.resolve({
        ...response,
        data: {
          size: response.headers[SIZE_HEADER],
          data: response.data,
        },
      });
    }
    return Promise.resolve(response);
  },
};

If there is a SIZE_HEADER in your response, you'll get an object { size: number, data: <original response data> }. If there is not a SIZE_HEADER then your data is unchanged. In your Zod schema you can do something like this for your response type:

z.union([z.object({ size: z.number(), data: <original response type> }), <original response type>])

@ecyrbe is there a way to access axios response data in v10 when validation fails?
variable from ajwootto example is in this case empty, I can only catch an error which contains stringified response in it's description, but I'd like to access response object.

My use case: I want to integrate zodios with React Query, but in case of errors in response I still want to pass data to React Query hook and show it on my frontend (only display error message in console for debugging). I don't want entire frontend to break when there is some minor issue in FE-BE contract.

tried something like:

try {
  const variable = await zodiosClient.get(...) // when ZOD finds errors variable is empty
} catch (error) {
  return error.response; // <-- this is also empty
}

Did I miss something in the docs?

ecyrbe commented

Since it's a validation error, the data that is not validated is encapsulated in a ZodiosError.
So you Can do :

try {
  const variable = await zodiosClient.get(...) // when ZOD finds errors variable is empty
} catch (error) {
  if (error instanceof ZodiosError)
      return error.data; // <-- this is the api response
}
stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

bumping to keep open

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

bumping to keep open

It would be nice if the project documentation were updated. The page describing how to use ZodiosPlugin is outdated, and contains references to invalid types.

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

not stale

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

not stale

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.