-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
136 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
"@fedify/fedify/runtime": "../../runtime/mod.ts", | ||
"@fedify/fedify/vocab": "../../vocab/mod.ts", | ||
"@fedify/fedify/webfinger": "../../webfinger/mod.ts", | ||
"@fedify/fedify/x/fresh": "../../x/fresh.ts", | ||
"markdown-it": "npm:markdown-it@^14.0.0", | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
"@fedify/fedify/runtime": "../../runtime/mod.ts", | ||
"@fedify/fedify/vocab": "../../vocab/mod.ts", | ||
"@fedify/fedify/webfinger": "../../webfinger/mod.ts", | ||
"@fedify/fedify/x/fresh": "../../x/fresh.ts", | ||
"markdown-it": "npm:markdown-it@^14.0.0", | ||
"preact": "https://esm.sh/[email protected]", | ||
"preact/": "https://esm.sh/[email protected]/", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,6 @@ | ||
import { FreshContext } from "$fresh/server.ts"; | ||
import { Handler } from "$fresh/server.ts"; | ||
import { federation } from "../federation/mod.ts"; | ||
import { integrateHandler } from "@fedify/fedify/x/fresh"; | ||
|
||
// This is the entry point to the Fedify middleware from the Fresh framework: | ||
export async function handler(request: Request, context: FreshContext) { | ||
// The `federation` object purposes to handle federation-related requests. | ||
// It is responsible for handling, for example, WebFinger queries, actor | ||
// dispatching, and incoming activities to the inbox. The definition of | ||
// the object is in the federation/mod.ts file. | ||
return await federation.handle(request, { | ||
// The context data is not used in this example, but it can be used to | ||
// store data (e.g., database connections) that is shared between | ||
// the different federation-related callbacks: | ||
contextData: undefined, | ||
|
||
// 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 Fresh framework to continue the request handling | ||
// by the Fresh: | ||
onNotFound: context.next.bind(context), | ||
|
||
// 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 Fresh 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 Fresh to share the same routes | ||
// and they do content negotiation depending on `Accept` header. | ||
// For instance, in this example, `/users/{handle}` can return JSON-LD | ||
// by the Fedify and redirects to the home page by the Fresh: | ||
async onNotAcceptable(_request: Request) { | ||
const response = await context.next(); | ||
if (response.status !== 404) return response; | ||
return new Response("Not acceptable", { | ||
status: 406, | ||
headers: { | ||
"Content-Type": "text/plain", | ||
Vary: "Accept", | ||
}, | ||
}); | ||
}, | ||
}); | ||
} | ||
export const handler: Handler = integrateHandler(federation, () => undefined); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* Fedify with Fresh | ||
* ================= | ||
* | ||
* This module contains some utilities for integrating Fedify with [Fresh], | ||
* a web framework for Deno. | ||
* | ||
* [Fresh]: https://fresh.deno.dev/ | ||
* | ||
* @module | ||
*/ | ||
import { | ||
Federation, | ||
FederationHandlerParameters, | ||
} from "../federation/middleware.ts"; | ||
|
||
interface FreshContext { | ||
next(): Promise<Response>; | ||
} | ||
|
||
/** | ||
* Create options for the `federation` object to integrate with Fresh. | ||
* | ||
* @example _middleware.ts | ||
* ``` typescript | ||
* import { FreshContext } from "$fresh/server.ts"; | ||
* import { federation } from "federation.ts"; // Import the `Federation` object | ||
* | ||
* export async function handler(request: Request, context: FreshContext) { | ||
* return await federation.handle(request, { | ||
* contextData: undefined, | ||
* ...integrateHandlerOptions(context), | ||
* }) | ||
* } | ||
* ``` | ||
* | ||
* @param context A Fresh context. | ||
* @returns Options for the {@link Federation.handle} method. | ||
*/ | ||
export function integrateHandlerOptions( | ||
context: FreshContext, | ||
): Omit<FederationHandlerParameters<void>, "contextData"> { | ||
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 Fresh framework to continue the request handling | ||
// by the Fresh: | ||
onNotFound: context.next.bind(context), | ||
|
||
// 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 Fresh 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 Fresh to share the same routes | ||
// and they do content negotiation depending on `Accept` header: | ||
async onNotAcceptable(_request: Request) { | ||
const response = await context.next(); | ||
if (response.status !== 404) return response; | ||
return new Response("Not acceptable", { | ||
status: 406, | ||
headers: { | ||
"Content-Type": "text/plain", | ||
Vary: "Accept", | ||
}, | ||
}); | ||
}, | ||
}; | ||
} | ||
|
||
/** | ||
* Create a Fresh middleware handler to integrate with the {@link Federation} | ||
* object. | ||
* | ||
* @example _middleware.ts | ||
* ``` typescript | ||
* import { federation } from "federation.ts"; // Import the `Federation` object | ||
* | ||
* export const handler = integrateHandler(federation, () => undefined); | ||
* ``` | ||
* | ||
* @param federation A {@link Federation} object to integrate with Fresh. | ||
* @param createContextData A function to create a context data for the | ||
* {@link Federation} object. | ||
* @returns A Fresh middleware handler. | ||
*/ | ||
export function integrateHandler< | ||
TContextData, | ||
TFreshContext extends FreshContext, | ||
>( | ||
federation: Federation<TContextData>, | ||
createContextData: ( | ||
req: Request, | ||
ctx: TFreshContext, | ||
) => TContextData | Promise<TContextData>, | ||
): (req: Request, ctx: TFreshContext) => Promise<Response> { | ||
return async ( | ||
request: Request, | ||
context: TFreshContext, | ||
): Promise<Response> => { | ||
let contextData = createContextData(request, context); | ||
if (contextData instanceof Promise) contextData = await contextData; | ||
return await federation.handle(request, { | ||
contextData, | ||
...integrateHandlerOptions(context), | ||
}); | ||
}; | ||
} |