trpc-openapi icon indicating copy to clipboard operation
trpc-openapi copied to clipboard

Set Custom Response Headers in OpenAPI

Open AarthiT opened this issue 2 years ago • 8 comments

trpc-openapi does not allow us to set response headers as part of responses of a path. To set custom response headers as part of swagger, we need to set headers within responses like given below.

paths:
  /ping:
    get:
      summary: Checks if the server is alive.
      responses:
        '200':
          description: OK
          headers:
            X-RateLimit-Limit:
              schema:
                type: integer
              description: Request limit per hour.

The current implementation only sets the description and content within the status code of each response.

AarthiT avatar Jun 23 '23 09:06 AarthiT

Have created a PR for the same

AarthiT avatar Jun 23 '23 12:06 AarthiT

I would like to be able to set headers and status code dynamically in a request handler.

Doing this

res.statusCode = 302
res.setHeader('location', redirectPath)

doesn't work because trpc-openapi takes over both status code and headers.

How do I best achieve this?

ViktorQvarfordt avatar Jul 01 '23 22:07 ViktorQvarfordt

trpc openApi doesn't recognise the status code and header set on the response and needs to be explicitly set again as part of meta.

export const appRouter = t.router({
  sayHello: t.procedure
    .meta({ /* 👉 */ openapi: { method: 'GET', path: '/say-hello', responseHeaders: 'location' } })
    .input(z.object({ name: z.string() }))
    .output(z.object({ greeting: z.string() }))
    .query(({ input }) => {
      return { greeting: `Hello ${input.name}!` };
    });
});

For now status code is still by default 200. We need to create a new PR to accommodate this change

AarthiT avatar Jul 03 '23 07:07 AarthiT

I would like to be able to set both headers and status code dynamically based on the request. So setting it in the .meta() function is not enough.

ViktorQvarfordt avatar Jul 03 '23 11:07 ViktorQvarfordt

+1 here. Need to be able to set headers for the response. Feeling the pain on this one as we need to specify that we're calling set-cookie on the /signin route.

divmgl avatar Sep 14 '23 17:09 divmgl

+1

gtolarc avatar Dec 07 '23 07:12 gtolarc

+1

CaptainAchilles avatar Dec 30 '23 12:12 CaptainAchilles

For what it's worth, there is a hacky workaround to get the headers set. It's just not defined via trpc-openapi


const router = t.router({
  asset: t.procedure
    .meta({ openapi: { method: 'GET', path: '/api/docs/{path}' } })
    .input(z.object({
      path: z.string()
    }))
    .output(z.any())
    .query(({ ctx, input }) => {
      Object.assign(ctx, {
        path: input.path
      });

      return readFileSync(absolutePath() + `/${input.path}`, 'utf-8');
    })
});

...
const server = http.createServer(createOpenApiHttpHandler({
  router: router,
  createContext: context,
  responseMeta: (opts) => {
    const path = opts?.ctx?.path;
    const mime = path ? mimeTypes.lookup(path) : false;
    if (mime) {
      return {
        headers: {
          'Content-Type': mime
        }
      };
    }
    return {};
  }
}));

CaptainAchilles avatar Dec 31 '23 09:12 CaptainAchilles