-
Notifications
You must be signed in to change notification settings - Fork 230
/
sseServer.ts
129 lines (116 loc) · 2.97 KB
/
sseServer.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
* This is an example of a server that utilizes the router.
*/
// Importing some console colors
import {
bold,
cyan,
green,
yellow,
} from "https://deno.land/std@0.94.0/fmt/colors.ts";
import {
Application,
Context,
isHttpError,
Router,
ServerSentEvent,
Status,
} from "../mod.ts";
interface Book {
id: string;
title: string;
author: string;
}
function notFound(ctx: Context) {
ctx.response.status = Status.NotFound;
ctx.response.body =
`<html><body><h1>404 - Not Found</h1><p>Path <code>${ctx.request.url}</code> not found.`;
}
const router = new Router();
router
.get("/", async (ctx) => {
await ctx.send(
{
root: `${Deno.cwd()}/examples/resources`,
path: "sseServer_index.html",
},
);
})
// for any clients that request the `/sse` endpoint, we will send a message
// every 2 seconds.
.get("/sse", (ctx: Context) => {
ctx.assert(
ctx.request.accepts("text/event-stream"),
Status.UnsupportedMediaType,
);
const connection = ctx.request.ip;
const target = ctx.sendEvents();
console.log(`${green("SSE connect")} ${cyan(connection)}`);
let counter = 0;
const id = setInterval(() => {
const evt = new ServerSentEvent(
"message",
{ hello: "world" },
{ id: counter++ },
);
target.dispatchEvent(evt);
}, 2000);
target.addEventListener("close", () => {
console.log(`${green("SSE disconnect")} ${cyan(connection)}`);
clearInterval(id);
});
});
const app = new Application();
// Logger
app.use(async (context, next) => {
await next();
const rt = context.response.headers.get("X-Response-Time");
console.log(
`${green(context.request.method)} ${cyan(context.request.url.pathname)} - ${
bold(
String(rt),
)
}`,
);
});
// Response Time
app.use(async (context, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
context.response.headers.set("X-Response-Time", `${ms}ms`);
});
// Error handler
app.use(async (context, next) => {
try {
await next();
} catch (err) {
if (isHttpError(err)) {
context.response.status = err.status;
const { message, status, stack } = err;
if (context.request.accepts("json")) {
context.response.body = { message, status, stack };
context.response.type = "json";
} else {
context.response.body = `${status} ${message}\n\n${stack ?? ""}`;
context.response.type = "text/plain";
}
} else {
console.log(err);
throw err;
}
}
});
// Use the router
app.use(router.routes());
app.use(router.allowedMethods());
// A basic 404 page
app.use(notFound);
app.addEventListener("listen", ({ hostname, port, serverType }) => {
console.log(
bold("Start listening on ") + yellow(`${hostname}:${port}`),
);
console.log(bold(" using HTTP server: " + yellow(serverType)));
});
await app.listen({ hostname: "127.0.0.1", port: 8000 });
console.log(bold("Finished."));