Skip to content

Conversation

Copy link

Copilot AI commented Nov 3, 2025

Headers set by Fastify before calling the Remix handler were being overridden by Remix response headers instead of merged. This broke use cases like adding Link preload headers in Fastify middleware.

// Before: Fastify's Link header was lost
instance.all('*', async (request, reply) => {
  reply.header('Link', '</fonts/my-font.woff2>; rel=preload; as=font');
  return handler(request, reply);  // Remix headers override Fastify's
});

// After: Headers are merged correctly
// Final response contains both Fastify and Remix Link headers

Changes

  • sendResponse in shared.ts: Collects response headers first, then merges with existing Fastify reply headers instead of replacing them
  • Header splitting: Handles Web Headers API behavior where multi-value headers like Link are combined with ", " (except Set-Cookie which remains separate)
  • Test coverage: Added test verifying Link headers from both Fastify and Remix appear in final response

Technical notes

The Web Headers API is lossy - it combines multi-value headers with ", " separators. We split on ", " to enable proper merging, which works correctly for Link headers but may incorrectly split headers containing literal commas in their values. This is an acceptable tradeoff given the Headers API provides no alternative.

Original prompt

This section details on the original issue you should resolve

<issue_title>Merge headers</issue_title>
<issue_description>These seems to be an issue, where if I send headers using Fastify, then anything that gets added by Remix is overriden, e.g.

Here I am adding link header:

await app.register(async (instance) => {
  instance.decorateRequest('cspNonce', null);

  instance.removeAllContentTypeParsers();

  instance.addContentTypeParser('*', (_request, payload, done) => {
    done(null, payload);
  });

  const handler = createRequestHandler({
    build: serverBuild,
    getLoadContext(request) {
      return {
        nonce: request.cspNonce,
        session: request.session as unknown as Session,
        visitor: request.visitor,
      };
    },
    mode: 'production',
  });

  instance.all('*', async (request, reply) => {    
    const links = getLinks(request.url);

    reply.header(
      'Link',
      [
        '</fonts/gabarito/Gabarito-VariableFont.woff2>; rel=preload; as=font; crossorigin',
        ...links,
      ].join(', '),
    );

    try {
      return handler(request, reply);
    } catch (error) {
      captureException({
        error,
        extra: {
          url: request.url,
        },
        message: 'could not render request',
      });

      return replyWithErrorPage(reply, error);
    }
  });
});

but the loaded route also send link header, which overrides my value from the above.

I would expect headers such as link to be merged.</issue_description>

Comments on the Issue (you are @copilot in this section)

@mcansh hey @lilouartz thanks for info i'll poke around soon @mcansh `0.0.0-experimental-1d46df2` looks like there's some edge cases where headers are added multiple times as im not limiting it to just `Link` headers, but should be good for a test :)

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@changeset-bot
Copy link

changeset-bot bot commented Nov 3, 2025

🦋 Changeset detected

Latest commit: 4b7fce2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@mcansh/remix-fastify Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI and others added 3 commits November 3, 2025 21:31
Co-authored-by: mcansh <11698668+mcansh@users.noreply.github.com>
Co-authored-by: mcansh <11698668+mcansh@users.noreply.github.com>
Co-authored-by: mcansh <11698668+mcansh@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue with merging headers in Fastify and Remix Merge headers from Fastify and Remix instead of overriding Nov 3, 2025
Copilot finished work on behalf of mcansh November 3, 2025 21:37
Copilot AI requested a review from mcansh November 3, 2025 21:37
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 3, 2025

More templates

npm i https://pkg.pr.new/@mcansh/remix-fastify@582

commit: 4b7fce2

@mcansh mcansh changed the title Merge headers from Fastify and Remix instead of overriding fix: merge Fastify headers with Remix headers instead of overriding them Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Merge headers

2 participants