1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { HttpHandler } from "https://esm.town/v/emarref/HttpHandler";
import { HttpMiddleware } from "https://esm.town/v/emarref/HttpMiddleware";
import { internalServerError, success } from "https://esm.town/v/emarref/HttpResponse";
export type Chain = {
add: (middleware: HttpMiddleware) => Promise<Chain>;
send: (response: Response) => HttpHandler;
};
export function chain(): Promise<Chain> {
const stack = new Set<HttpMiddleware>();
async function getChain(): Promise<Chain> {
return { add, send };
}
const add: Chain["add"] = (middleware) => {
stack.add(middleware);
return getChain();
};
const send: Chain["send"] = (defaultResponse) => {
return async (request) => {
const queue = Array.from(stack);
let response = defaultResponse.clone();
let middleware: HttpMiddleware | undefined;
let happy = true;
async function loop() {
middleware = queue.shift();
if (!middleware) {
return;
}
const handler = middleware(async () => response);
try {
response = await handler(request);
} catch (err) {
happy = false;
if (err instanceof Response) {
response = err;
} else {
response = internalServerError(err);
}
}
}
do {
await loop();
} while (happy && middleware);
return response;
};
};
return getChain();
}
export function add(middleware: HttpMiddleware) {
return function({ add }: Chain) {
return add(middleware);
};
}
export function send(response?: Response) {
return function({ send }: Chain) {
return send(response ?? success());
};
}