@fedify/fedify
Version:
An ActivityPub server framework
54 lines (53 loc) • 2.21 kB
JavaScript
/**
* Create a Hono middleware to integrate with the {@link Federation} object.
*
* @typeParam TContextData A type of the context data for the {@link Federation}
* object.
* @typeParam THonoContext A type of the Hono context.
* @param federation A {@link Federation} object to integrate with Hono.
* @param contextDataFactory A function to create a context data for the
* {@link Federation} object.
* @returns A Hono middleware.
*/
export function federation(federation, contextDataFactory) {
return async (ctx, next) => {
let contextData = contextDataFactory(ctx);
if (contextData instanceof Promise)
contextData = await contextData;
return await federation.fetch(ctx.req.raw, {
contextData,
...integrateFetchOptions(ctx, next),
});
};
}
function integrateFetchOptions(ctx, next) {
return {
// If the `federation` object finds a request not responsible for it
// (i.e., not a federation-related request), it will call the `next`
// provided by the Hono framework to continue the request handling
// by the Hono:
async onNotFound(_req) {
await next();
return ctx.res;
},
// Similar to `onNotFound`, but slightly more tricky one.
// When the `federation` object finds a request not acceptable type-wise
// (i.e., a user-agent doesn't want JSON-LD), it will call the `next`
// provided by the Hono framework so that it renders HTML if there's some
// page. Otherwise, it will simply return a 406 Not Acceptable response.
// This kind of trick enables the Fedify and Hono to share the same routes
// and they do content negotiation depending on `Accept` header:
async onNotAcceptable(_req) {
await next();
if (ctx.res.status !== 404)
return ctx.res;
return new Response("Not acceptable", {
status: 406,
headers: {
"Content-Type": "text/plain",
Vary: "Accept",
},
});
},
};
}