-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.ts
94 lines (77 loc) · 2.45 KB
/
server.ts
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import {
createServer,
IncomingMessage,
ServerResponse,
OutgoingHttpHeaders,
} from "http";
import { logger } from "./logging";
import { FindsDecentralizedIDOfHandle } from "./handles";
export const defaultFallbackUrl =
"https://{domain}?utm_source=handles-server&utm_medium=http&utm_campaign=redirect&utm_term={handle}";
function respond(
res: ServerResponse,
body: string,
status: number = 200,
headers: OutgoingHttpHeaders = {},
): void {
res.writeHead(status, { "Content-Type": "text/plain", ...headers });
res.write(body);
res.end();
}
export type HttpConfiguration = {
fallbackUrl: string;
};
export async function handleRequest(
req: IncomingMessage,
res: ServerResponse,
handles: FindsDecentralizedIDOfHandle,
options: HttpConfiguration,
) {
if (req.url === "/healthz") {
return respond(res, "OK", 200);
}
const handle = req.headers.host || "";
const domain = handle.split(".").slice(1).join(".").toLowerCase();
let log = logger.child({ handle, domain, url: req.url });
if (!handle || !domain) {
respond(res, "A request must include a Handle in the `host` header.", 400);
return log.debug("Rejected request without a host header.", {
status: 400,
});
}
const did = await handles.findDecentralizedIDofHandle(handle);
log = log.child({ did });
log.debug("Obtained `did` from provider.");
if (did && req.url === "/.well-known/atproto-did") {
respond(res, did);
return log.debug("Successfully verified Handle.");
}
if (!did && req.url === "/.well-known/atproto-did") {
respond(res, "Handle cannot be verified, did not found.", 404);
return log.debug("Denied verification request due to missing did.");
}
if (did) {
respond(res, "", 307, { location: `https://bsky.app/profile/${handle}` });
return log.debug("Redirected to Bluesky profile.");
}
let noProfileDestination = options.fallbackUrl;
Object.entries({ domain, handle }).forEach(
([token, value]) =>
(noProfileDestination = noProfileDestination.replaceAll(
`{${token}}`,
value,
)),
);
respond(res, "", 307, { location: noProfileDestination });
return log.debug(
{ noProfileDestination },
"Redirected to no profile destination.",
);
}
export function expose(handles: FindsDecentralizedIDOfHandle) {
return createServer((req, res) =>
handleRequest(req, res, handles, {
fallbackUrl: process.env.HANDLES_FALLBACK_URL || defaultFallbackUrl,
}),
);
}