-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
82 lines (70 loc) · 2.38 KB
/
index.ts
File metadata and controls
82 lines (70 loc) · 2.38 KB
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
import { serve } from 'bun';
interface Router {
name: String;
rule: String;
provider: 'internal' | 'docker';
service: String;
}
serve({
port: process.env.PORT || 3000,
async fetch(req) {
// Extract path from the current URL path
const url = new URL(req.url);
const traefikInstances = url.pathname.split('/');
traefikInstances.shift();
if (!traefikInstances.length || traefikInstances[0] === '') {
const message = `No Traefik FQDN provided! Example: "${url}traefik.server1.example.com/traefik.server2.example.com"`;
const status = 400;
console.error(message, status);
return new Response(message, { status });
}
const routers = {};
const services = {};
for await (const traefikEndpoint of traefikInstances) {
// send API request to traefik to get router and service details
const responseRouters = await fetch(
`${process.env.HTTPS === 'true' ? 'https' : 'http'}://${traefikEndpoint}/api/http/routers`
);
if (!responseRouters.ok) {
const message = `Unable to access Traefik API server, is it reachable?\n${
responseRouters ? `${responseRouters.statusText} - ` : ''
}${traefikEndpoint}`;
const status = responseRouters ? responseRouters.status : 500;
console.error(message, status);
return new Response(message, { status });
}
const routersRaw = await responseRouters.json();
const joinName = (input: String) =>
`${input.split('@')[0]}_${traefikEndpoint.replaceAll('.', '_')}`.replaceAll('-', '_');
// compile data for the routing traefik to understand
// routers
routersRaw
.filter((router: Router) => router.provider === 'docker')
.forEach((router: Router) => {
const routerName = joinName(router.name);
routers[routerName] = {
service: traefikEndpoint,
rule: `${router.rule} && PathPrefix(\`/.well-known/acme-challenge/\`)`,
};
});
// service
services[traefikEndpoint] = {
loadBalancer: {
servers: [{ url: `http://${traefikEndpoint}:80` }],
},
};
}
const finalConfig = {
http: {
services,
routers,
},
};
// send response
return new Response(JSON.stringify(finalConfig), {
headers: {
'Content-Type': 'application/json',
},
});
},
});