hey-api / openapi-ts

✨ Turn your OpenAPI specification into a beautiful TypeScript client

Home Page:https://heyapi.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Accessing Both Response Body and Headers

Judx opened this issue · comments

Description

Firstly, I want to express my gratitude for continuing the development of the ferdikoomen/openapi-typescript-codegen project.

I'm currently integrating the "Hey API" into a simple web application that requires bearer authentication, and I've run into an issue with accessing both the response body and headers simultaneously.

Issue Description:
In my scenario, critical data required for validation is located in the response headers. Unfortunately, despite various attempts, I haven't been able to extract both the body and headers from the response using the generated client.

Attempts to Resolve:

  • I tried using services.response = 'response' to change the default behavior.
  • I tried interceptors, hoping to capture the headers during the response handling.
  • I explored all available configurations in the config.ts file.

Despite these efforts, the request().results method still does not return both headers and the body. Here’s a snippet of my currently generated request function:

// core/request.js

const responseBody = await getResponseBody(response);
const responseHeader = getResponseHeader(response, options.responseHeader);

const result: ApiResult = {
  url,
  ok: response.ok,
  status: response.status,
  statusText: response.statusText,
  body: responseHeader ?? responseBody,
};

resolve(result);

Desired Outcome:
I would like the ability to configure the API client such that it can return an object containing both the response body and headers without requiring extensive modifications to the generated code.

Questions:

  1. Is there an existing configuration option I've overlooked that would allow access to both body and headers?
  2. Could this functionality be considered for future updates if it's not currently possible?

Thank you for your attention and assistance. I look forward to any suggestions or guidance you can provide.

OpenAPI specification (optional)

No response

Configuration

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
    input: 'openapi.yaml',
    output: 'src/schemas',
    client: 'fetch',
    services: {
        export: true,
        response: 'response',
    },
});

System information (optional)

No response

Here is my working solution.

Keep the same configuration ie.services.response set to response and patch these generated files:

  • core/ApiResult.ts:
export type ApiResult<TData = any> = {
  readonly headers: Headers; // add headers
  readonly body: TData;
  readonly ok: boolean;
  readonly status: number;
  readonly statusText: string;
  readonly url: string;
};
  • core/requests.ts:
/**
 * Request method
 * @param config The OpenAPI configuration object
 * @param options The request options from the service
 * @returns CancelablePromise<ApiResult<T>>
 * @throws ApiError
 */
export const request = <T>(
  config: OpenAPIConfig,
  options: ApiRequestOptions,
): CancelablePromise<ApiResult<T>> => {
  return new CancelablePromise(async (resolve, reject, onCancel) => {
    try {
      const url = getUrl(config, options);
      const formData = getFormData(options);
      const body = getRequestBody(options);
      const headers = await getHeaders(config, options);

      if (!onCancel.isCancelled) {
        let response = await sendRequest(
          config,
          options,
          url,
          body,
          formData,
          headers,
          onCancel,
        );

        for (const fn of config.interceptors.response._fns) {
          response = await fn(response);
        }

        const responseBody = await getResponseBody(response);

        const result: ApiResult = {
          url,
          ok: response.ok,
          status: response.status,
          statusText: response.statusText,
          headers: response.headers, // add response headers
          body: responseBody, // keep response body
        };

        catchErrorCodes(options, result);

        resolve(result);
      }
    } catch (error) {
      reject(error);
    }
  });
};

Thanks @bhuisgen! However I am looking for a configuration that would do the same.

  1. Is there an existing configuration option I've overlooked that would allow access to both body and headers?

I believe today, you only get the body from result. @Judx would you be okay with returning the whole object?

@Judx @bhuisgen I am not sure if you're using Fetch API, but if so, can you try the new Fetch API client? You can view a demo to see it in action. You'd have access to the whole response with it. Let me know your thoughts!

Thanks @mrlubos @hey-api/client-fetch looks cool. I will test it at some point.