-
Notifications
You must be signed in to change notification settings - Fork 252
Expand file tree
/
Copy pathhttpzip.js
More file actions
102 lines (90 loc) · 2.63 KB
/
httpzip.js
File metadata and controls
102 lines (90 loc) · 2.63 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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
* Copyright (c) 2016-2021 Moddable Tech, Inc.
* Copyright (c) Wilberforce
*
* This file is part of the Moddable SDK.
*
* This work is licensed under the
* Creative Commons Attribution 4.0 International License.
* To view a copy of this license, visit
* <http://creativecommons.org/licenses/by/4.0>.
* or send a letter to Creative Commons, PO Box 1866,
* Mountain View, CA 94042, USA.
*
*/
import { Bridge, HTTPServer } from "bridge/webserver";
import Resource from "Resource";
import {ZIP} from "zip"
const mime = new Map;
mime.set("js", "application/javascript");
mime.set("css", "text/css");
mime.set("ico", "image/vnd.microsoft.icon");
mime.set("txt", "text/plain");
mime.set("htm", "text/html");
mime.set("html", "text/html");
mime.set("svg", "image/svg+xml");
mime.set("png", "image/png");
mime.set("gif", "image/gif");
mime.set("webp", "image/webp");
mime.set("jpg", "image/jpeg");
mime.set("jpeg", "image/jpeg");
export class BridgeHttpZip extends Bridge {
constructor(resource) {
super();
this.archive = new ZIP(new Resource(resource));
}
handler(req, message, value, etc) {
switch (message) {
case HTTPServer.status:
// redirect home page
if (value === '/') value='/index.html';
req.path = value;
try {
req.data = this.archive.file(req.path.slice(1)); // drop leading / to match zip content
req.etag = "mod-" + req.data.crc.toString(16);
}
catch {
delete req.data;
delete req.etag;
return this.next?.handler(req, message, value, etc);
}
break;
case HTTPServer.header:
req.match ||= ("if-none-match" === value) && (req.etag === etc);
return this.next?.handler(req, message, value, etc);
case HTTPServer.prepareResponse:
if (req.match) {
return {
status: 304,
headers: [
"ETag", req.etag,
]
};
}
if (!req.data) {
trace(`prepareResponse: missing file ${req.path}\n`);
return this.next?.handler(req, message, value, etc);
}
req.data.current = 0;
const result = {
headers: [
"Content-type", mime.get(req.path.split('.').pop()) ?? "text/plain",
"Content-length", req.data.length,
"ETag", req.etag,
"Cache-Control", "max-age=60"
],
body: true
}
if (8 === req.data.method) // Compression Method
result.headers.push("Content-Encoding", "deflate");
return result;
case HTTPServer.responseFragment:
if (req.data.current >= req.data.length)
return;
const chunk = req.data.read(ArrayBuffer, (value > 1536) ? 1536 : value);
req.data.current += chunk.byteLength;
return chunk;
}
}
}
Object.freeze(mime);