Skip to content

Commit 150998a

Browse files
committed
Merge tag '2.0.4'
Fedify 2.0.4
2 parents f5543fc + b929654 commit 150998a

3 files changed

Lines changed: 57 additions & 5 deletions

File tree

CHANGES.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@ To be released.
146146
[#599]: https://github.com/fedify-dev/fedify/pull/599
147147

148148

149+
Version 2.0.4
150+
-------------
151+
152+
Released on March 11, 2026.
153+
154+
### @fedify/fastify
155+
156+
- Fixed the default `onNotAcceptable` handler in `@fedify/fastify` to
157+
create a fresh `Response` for each request instead of reusing a shared
158+
singleton instance. [[#612] by Lee Dogeon]
159+
160+
[#612]: https://github.com/fedify-dev/fedify/pull/612
161+
162+
149163
Version 2.0.3
150164
-------------
151165

packages/fastify/src/index.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,43 @@ test("Fedify should handle notAcceptable and return 406", async () => {
129129
await fastify.close();
130130
});
131131

132+
test("Fedify should create a fresh 406 response for each request", async () => {
133+
const fastify = Fastify({ logger: false });
134+
const federation = createFederation<void>({ kv: new MemoryKvStore() });
135+
136+
federation.setActorDispatcher(
137+
"/users/{identifier}",
138+
(_ctx: RequestContext<void>, identifier: string) => {
139+
return new Person({
140+
id: new URL(`https://example.com/users/${identifier}`),
141+
preferredUsername: identifier,
142+
name: `User ${identifier}`,
143+
});
144+
},
145+
);
146+
147+
await fastify.register(fedifyPlugin, { federation });
148+
await fastify.ready();
149+
150+
const firstResponse = await fastify.inject({
151+
method: "GET",
152+
url: "/users/alice",
153+
headers: { "Accept": "text/html" },
154+
});
155+
const secondResponse = await fastify.inject({
156+
method: "GET",
157+
url: "/users/alice",
158+
headers: { "Accept": "text/html" },
159+
});
160+
161+
assert.equal(firstResponse.statusCode, 406);
162+
assert.equal(firstResponse.body, "Not Acceptable");
163+
assert.equal(secondResponse.statusCode, 406);
164+
assert.equal(secondResponse.body, "Not Acceptable");
165+
166+
await fastify.close();
167+
});
168+
132169
test("Fedify should handle notAcceptable with custom error handler", async () => {
133170
const fastify = Fastify({ logger: false });
134171
const federation = createFederation<void>({ kv: new MemoryKvStore() });

packages/fastify/src/index.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const fedifyPluginCore: FastifyPluginAsync<FedifyPluginOptions<unknown>> = (
7676

7777
const response = await federation.fetch(webRequest, {
7878
contextData,
79-
onNotAcceptable: () => defaultNotAcceptableResponse,
79+
onNotAcceptable: createDefaultNotAcceptableResponse,
8080
onNotFound: () => dummyNotFoundResponse,
8181
...errorHandlers,
8282
});
@@ -101,10 +101,11 @@ const fedifyPlugin: FastifyPluginAsync<FedifyPluginOptions<unknown>> = fp(
101101
);
102102

103103
const dummyNotFoundResponse = new Response("", { status: 404 });
104-
const defaultNotAcceptableResponse = new Response("Not Acceptable", {
105-
status: 406,
106-
headers: { "Content-Type": "text/plain", Vary: "Accept" },
107-
});
104+
const createDefaultNotAcceptableResponse = () =>
105+
new Response("Not Acceptable", {
106+
status: 406,
107+
headers: { "Content-Type": "text/plain", Vary: "Accept" },
108+
});
108109

109110
/**
110111
* Convert Fastify request to Web API Request.

0 commit comments

Comments
 (0)