Skip to content

Cannot modify headers when using zod schemas #209

@bienzaaron

Description

@bienzaaron

request headers cannot be overridden when using zod schemas. The following code works with regular json schemas:

const Fastify = require("fastify");

const fastify = Fastify({ logger: true });

fastify.get("/", {
  schema: {
    headers: {
      type: "object",
      properties: {
        "x-custom-header": { type: "string" },
      },
      additionalProperties: true,
    }
  },
  onResponse: async (request, reply) => {
    request.headers["x-custom-header"] = "custom-value";
    request.headers["x-custom-header-2"] = "custom-value-2";
    // logs added headers
    console.log(request.headers);
  },
}, async (request, reply) => {
  return { hello: "world" };
});

fastify.listen({ host: "::", port: 4001 });

logs:

{"level":30,"time":1757001095322,"pid":19127,"hostname":"bcd0744fbac0","msg":"Server listening at http://[::]:4001"}
{"level":30,"time":1757001098274,"pid":19127,"hostname":"bcd0744fbac0","reqId":"req-1","req":{"method":"GET","url":"/","host":"localhost:4001","remoteAddress":"::1","remotePort":54197},"msg":"incoming request"}
{
  host: 'localhost:4001',
  'user-agent': 'curl/8.7.1',
  accept: '*/*',
  'x-custom-header': 'custom-value',
  'x-custom-header-2': 'custom-value-2'
}
{"level":30,"time":1757001098277,"pid":19127,"hostname":"bcd0744fbac0","reqId":"req-1","res":{"statusCode":200},"responseTime":2.5528750121593475,"msg":"request completed"}

When zod schemas are used, the headers object becomes immutable (even with those headers defined in the schema):

const Fastify = require("fastify");
const { serializerCompiler, validatorCompiler } = require(
  "fastify-type-provider-zod",
);
const { z } = require("zod");

const fastify = Fastify({ logger: true });

fastify.setValidatorCompiler(validatorCompiler);
fastify.setSerializerCompiler(serializerCompiler);

fastify.get("/", {
  schema: {
    headers: z.looseObject({
      "x-custom-header": z.string().optional(),
    }),
  },
  onResponse: async (request, reply) => {
    request.headers["x-custom-header"] = "custom-value";
    request.headers["x-custom-header-2"] = "custom-value-2";
    // does not log added headers
    console.log(request.headers);
  },
}, async (request, reply) => {
  return { hello: "world" };
});

fastify.listen({ host: "::", port: 4001 });

logs:

{"level":30,"time":1757000947619,"pid":18843,"hostname":"bcd0744fbac0","msg":"Server listening at http://[::]:4001"}
{"level":30,"time":1757000950327,"pid":18843,"hostname":"bcd0744fbac0","reqId":"req-1","req":{"method":"GET","url":"/","host":"localhost:4001","remoteAddress":"::1","remotePort":53510},"msg":"incoming request"}
{ host: 'localhost:4001', 'user-agent': 'curl/8.7.1', accept: '*/*' }
{"level":30,"time":1757000950331,"pid":18843,"hostname":"bcd0744fbac0","reqId":"req-1","res":{"statusCode":200},"responseTime":2.9082910120487213,"msg":"request completed"}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions