Skip to content

Commit ca4aa5e

Browse files
authored
perf: various updates (#16)
1 parent ec15e8c commit ca4aa5e

12 files changed

+465
-150
lines changed

Diff for: .github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
with:
1616
deno-version: v1.x
1717
- name: Run tests
18-
run: deno test --allow-env --allow-read=. --allow-net=api.github.com
18+
run: deno test --allow-env --allow-read=. --allow-net=api.github.com,0.0.0.0,localhost
1919
- name: Deploy to Deno Deploy
2020
uses: denoland/deployctl@v1
2121
with:

Diff for: dprint.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
"**/*-lock.json"
55
],
66
"plugins": [
7-
"https://plugins.dprint.dev/typescript-0.88.3.wasm",
8-
"https://plugins.dprint.dev/json-0.19.0.wasm",
9-
"https://plugins.dprint.dev/markdown-0.16.2.wasm",
10-
"https://plugins.dprint.dev/prettier-0.27.0.json@3557a62b4507c55a47d8cde0683195b14d13c41dda66d0f0b0e111aed107e2fe"
7+
"https://plugins.dprint.dev/typescript-0.88.7.wasm",
8+
"https://plugins.dprint.dev/json-0.19.1.wasm",
9+
"https://plugins.dprint.dev/markdown-0.16.3.wasm",
10+
"https://plugins.dprint.dev/prettier-0.31.0.json@8808616145fecc35574b79e78620f7fb241afba445201e64042dc78e01a1022b"
1111
]
1212
}

Diff for: handleRequest.test.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { assertEquals } from "./deps.test.ts";
2-
import { handleRequest } from "./handleRequest.ts";
2+
import { createRequestHandler } from "./handleRequest.ts";
3+
import { RealClock } from "./utils/clock.ts";
4+
5+
const connInfo: Deno.ServeHandlerInfo = {
6+
remoteAddr: {
7+
transport: "tcp",
8+
hostname: "127.0.0.1",
9+
port: 80,
10+
},
11+
};
312

413
Deno.test("should get info.json", async () => {
14+
const { handleRequest } = createRequestHandler(new RealClock());
515
const response = await handleRequest(
616
new Request("https://plugins.dprint.dev/info.json"),
17+
connInfo,
718
);
819
assertEquals(response.headers.get("content-type"), "application/json; charset=utf-8");
920
const data = await response.json();
@@ -15,17 +26,21 @@ Deno.test("should get info.json", async () => {
1526
});
1627

1728
Deno.test("should get cli.json", async () => {
29+
const { handleRequest } = createRequestHandler(new RealClock());
1830
const response = await handleRequest(
1931
new Request("https://plugins.dprint.dev/cli.json"),
32+
connInfo,
2033
);
2134
assertEquals(response.headers.get("content-type"), "application/json; charset=utf-8");
2235
const data = await response.json();
2336
assertEquals(typeof data.version, "string");
2437
});
2538

2639
async function getRedirectUrl(url: string) {
40+
const { handleRequest } = createRequestHandler(new RealClock());
2741
const response = await handleRequest(
2842
new Request(url),
43+
connInfo,
2944
);
3045
assertEquals(response.status, 302);
3146
return response.headers.get("location")!;

Diff for: handleRequest.ts

+106-94
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { renderHome } from "./home.tsx";
22
import oldMappings from "./old_redirects.json" assert { type: "json" };
33
import { tryResolveLatestJson, tryResolvePluginUrl, tryResolveSchemaUrl } from "./plugins.ts";
44
import { readInfoFile } from "./readInfoFile.ts";
5-
import { fetchCached, getCliInfo } from "./utils/mod.ts";
5+
import { Clock } from "./utils/clock.ts";
6+
import { createFetchCacher, getCliInfo } from "./utils/mod.ts";
67

78
const contentTypes = {
89
css: "text/css; charset=utf-8",
@@ -12,73 +13,112 @@ const contentTypes = {
1213
wasm: "application/wasm",
1314
};
1415

15-
export async function handleRequest(request: Request) {
16-
const url = new URL(request.url);
17-
const newUrl = await resolvePluginOrSchemaUrl(url);
18-
if (newUrl != null) {
19-
const contentType = newUrl.endsWith(".json")
20-
? contentTypes.json
21-
: newUrl.endsWith(".wasm")
22-
? contentTypes.wasm
23-
: contentTypes.plain;
24-
return handleConditionalRedirectRequest({
25-
request,
26-
url: newUrl,
27-
contentType,
28-
});
29-
}
30-
31-
const userLatestInfo = await tryResolveLatestJson(url);
32-
if (userLatestInfo != null) {
33-
if (userLatestInfo === 404) {
34-
return new Response("Not Found", {
35-
status: 404,
36-
});
16+
export function createRequestHandler(clock: Clock) {
17+
const { fetchCached } = createFetchCacher(clock);
18+
return {
19+
async handleRequest(request: Request, info: Deno.ServeHandlerInfo) {
20+
const url = new URL(request.url);
21+
const newUrl = await resolvePluginOrSchemaUrl(url);
22+
if (newUrl != null) {
23+
const contentType = newUrl.endsWith(".json")
24+
? contentTypes.json
25+
: newUrl.endsWith(".wasm")
26+
? contentTypes.wasm
27+
: contentTypes.plain;
28+
return handleConditionalRedirectRequest({
29+
request,
30+
url: newUrl,
31+
contentType,
32+
hostname: info.remoteAddr.hostname,
33+
});
34+
}
35+
36+
const userLatestInfo = await tryResolveLatestJson(url);
37+
if (userLatestInfo != null) {
38+
if (userLatestInfo === 404) {
39+
return new Response("Not Found", {
40+
status: 404,
41+
});
42+
} else {
43+
return createJsonResponse(JSON.stringify(userLatestInfo, undefined, 2), request);
44+
}
45+
}
46+
47+
if (url.pathname.startsWith("/info.json")) {
48+
const infoFileData = await readInfoFile();
49+
return createJsonResponse(JSON.stringify(infoFileData, null, 2), request);
50+
}
51+
52+
if (url.pathname.startsWith("/cli.json")) {
53+
const cliInfo = await getCliInfo();
54+
return createJsonResponse(JSON.stringify(cliInfo, null, 2), request);
55+
}
56+
57+
if (url.pathname === "/style.css") {
58+
return Deno.readTextFile("./style.css").then(text =>
59+
new Response(text, {
60+
headers: {
61+
"content-type": "text/css; charset=utf-8",
62+
},
63+
status: 200,
64+
})
65+
);
66+
}
67+
68+
if (url.pathname === "/") {
69+
return renderHome().then(home =>
70+
new Response(home, {
71+
headers: {
72+
"content-type": contentTypes.html,
73+
},
74+
status: 200,
75+
})
76+
).catch(err =>
77+
new Response(`${err.toString?.() ?? err}`, {
78+
headers: {
79+
"content-type": contentTypes.plain,
80+
},
81+
status: 500,
82+
})
83+
);
84+
}
85+
86+
return create404Response();
87+
},
88+
};
89+
90+
// This is done to allow the playground to access these files
91+
function handleConditionalRedirectRequest(params: {
92+
request: Request;
93+
url: string;
94+
contentType: string;
95+
hostname: string;
96+
}) {
97+
if (shouldDirectlyServeFile(params.request)) {
98+
return fetchCached(params)
99+
.then(result => {
100+
if (result.kind === "error") {
101+
return result.response;
102+
}
103+
104+
return new Response(result.body, {
105+
headers: {
106+
"content-type": params.contentType,
107+
// allow the playground to download this
108+
"Access-Control-Allow-Origin": getAccessControlAllowOrigin(params.request),
109+
},
110+
status: 200,
111+
});
112+
}).catch(err => {
113+
console.error(err);
114+
return new Response("Internal Server Error", {
115+
status: 500,
116+
});
117+
});
37118
} else {
38-
return createJsonResponse(JSON.stringify(userLatestInfo, undefined, 2), request);
119+
return createRedirectResponse(params.url);
39120
}
40121
}
41-
42-
if (url.pathname.startsWith("/info.json")) {
43-
const infoFileData = await readInfoFile();
44-
return createJsonResponse(JSON.stringify(infoFileData, null, 2), request);
45-
}
46-
47-
if (url.pathname.startsWith("/cli.json")) {
48-
const cliInfo = await getCliInfo();
49-
return createJsonResponse(JSON.stringify(cliInfo, null, 2), request);
50-
}
51-
52-
if (url.pathname === "/style.css") {
53-
return Deno.readTextFile("./style.css").then(text =>
54-
new Response(text, {
55-
headers: {
56-
"content-type": "text/css; charset=utf-8",
57-
},
58-
status: 200,
59-
})
60-
);
61-
}
62-
63-
if (url.pathname === "/") {
64-
return renderHome().then(home =>
65-
new Response(home, {
66-
headers: {
67-
"content-type": contentTypes.html,
68-
},
69-
status: 200,
70-
})
71-
).catch(err =>
72-
new Response(`${err.toString?.() ?? err}`, {
73-
headers: {
74-
"content-type": contentTypes.plain,
75-
},
76-
status: 500,
77-
})
78-
);
79-
}
80-
81-
return create404Response();
82122
}
83123

84124
async function resolvePluginOrSchemaUrl(url: URL) {
@@ -87,41 +127,13 @@ async function resolvePluginOrSchemaUrl(url: URL) {
87127
?? await tryResolveSchemaUrl(url);
88128
}
89129

90-
// This is done to allow the playground to access these files
91-
function handleConditionalRedirectRequest(params: { request: Request; url: string; contentType: string }) {
92-
if (shouldDirectlyServeFile(params.request)) {
93-
return fetchCached(params.url)
94-
.then(result => {
95-
if (result.kind === "error") {
96-
return result.response;
97-
}
98-
99-
return new Response(result.body, {
100-
headers: {
101-
"content-type": params.contentType,
102-
// allow the playground to download this
103-
"Access-Control-Allow-Origin": getAccessControlAllowOrigin(params.request),
104-
},
105-
status: 200,
106-
});
107-
}).catch(err => {
108-
console.error(err);
109-
return new Response("Internal Server Error", {
110-
status: 500,
111-
});
112-
});
113-
} else {
114-
return createRedirectResponse(params.url);
115-
}
116-
}
117-
118130
function getAccessControlAllowOrigin(request: Request) {
119131
const origin = request.headers.get("origin");
120132
return origin != null && new URL(origin).hostname === "localhost" ? origin : "https://dprint.dev";
121133
}
122134

123135
function shouldDirectlyServeFile(request: Request) {
124-
// directly serve for when Deno makes a request
136+
// directly serve for when Deno makes a request in order to fix the content type
125137
if (request.headers.get("user-agent")?.startsWith("Deno/")) {
126138
return true;
127139
}

Diff for: import_map.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"imports": {
33
"preact": "https://esm.sh/[email protected]?pin=v135",
4-
"preact/": "https://esm.sh/[email protected]?pin=v135/",
4+
"preact/": "https://esm.sh/[email protected]&pin=v135/",
55
"preact-render-to-string": "https://esm.sh/*[email protected]?pin=v135"
66
}
77
}

Diff for: main.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
import { handleRequest } from "./handleRequest.ts";
1+
import { createRequestHandler } from "./handleRequest.ts";
2+
import { RealClock } from "./utils/clock.ts";
23

3-
Deno.serve((request) => handleRequest(request));
4+
const { handleRequest } = createRequestHandler(new RealClock());
5+
6+
Deno.serve((request, info) => handleRequest(request, info));

0 commit comments

Comments
 (0)