@amritk/nish-x86_64-linux 0.23.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/nish +0 -0
- package/docs/AI.md +50 -23
- package/package.json +1 -1
- package/runtime/browser.mjs +4 -3
- package/runtime/core/arrays.d.ts +0 -2
- package/runtime/core/arrays.mjs +0 -2
- package/runtime/core/host.d.ts +8 -0
- package/runtime/core/host.mjs +50 -2
- package/runtime/core/numbers.mjs +2 -3
- package/runtime/nish.d.ts +100 -4
- package/runtime/nish.h +34 -0
- package/runtime/nish.mjs +23 -5
- package/runtime/node.mjs +57 -6
- package/runtime/runtime-net.c +45 -4
- package/runtime/runtime-os.c +115 -12
- package/runtime/runtime-term.c +2 -2
- package/runtime/runtime.c +1 -1
- package/scripts/build.sh +13 -3
- package/std/README.md +44 -7
- package/std/cli-args.ts +1216 -0
- package/std/cli-flags.ts +585 -0
- package/std/cli.ts +308 -19
- package/std/compress/checksum.ts +290 -0
- package/std/compress/deflate.ts +2790 -0
- package/std/compress/gzip.ts +761 -0
- package/std/compress/zlib.ts +168 -0
- package/std/crypto/LICENSE-fiat-crypto-p384 +21 -0
- package/std/crypto/p256.ts +63 -1
- package/std/crypto/p384.ts +6044 -0
- package/std/crypto/pki-roots.ts +322 -0
- package/std/crypto/pki.ts +1207 -0
- package/std/crypto/rsa.ts +663 -0
- package/std/crypto/sha256.ts +2 -3
- package/std/crypto/x25519.ts +3 -4
- package/std/crypto/x509.ts +1054 -58
- package/std/net/dns-config.ts +734 -0
- package/std/net/dns-message.ts +517 -0
- package/std/net/dns-resolver.ts +1015 -0
- package/std/net/dns.ts +478 -0
- package/std/net/http-compress.ts +393 -0
- package/std/net/http1-client.ts +1227 -0
- package/std/net/http1-server.ts +101 -1
- package/std/net/http1.ts +9 -9
- package/std/net/tls/client.ts +1094 -0
- package/std/net/tls/codec.ts +585 -3
- package/std/net/tls/record-client.ts +1192 -0
- package/std/net/tls/verify.ts +221 -0
- package/std/net/tls-tcp.ts +642 -11
- package/std/net/tls.ts +2 -2
- package/std/net/url.ts +559 -4
- package/std/yaml-write.ts +415 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nish/net/http-compress` — content coding for HTTP responses (RFC 9110
|
|
3
|
+
* §8.4 and §12.5.3): reading a request's `Accept-Encoding` and compressing a
|
|
4
|
+
* body with `Content-Encoding: gzip`, for any of the three servers.
|
|
5
|
+
*
|
|
6
|
+
* import { DEFLATE_FAST } from "nish/compress/deflate";
|
|
7
|
+
* import { HTTP_CODING_GZIP, HttpCompressor } from "nish/net/http-compress";
|
|
8
|
+
*
|
|
9
|
+
* const enc = new HttpCompressor(DEFLATE_FAST, 1024, 65536); // once per thread
|
|
10
|
+
* // HTTP/1.1, in one call:
|
|
11
|
+
* conn.respondEncoded(200, names, values, body, 0, n, enc, conn.acceptEncoding());
|
|
12
|
+
* // HTTP/2 or HTTP/3, by hand:
|
|
13
|
+
* const coding: i32 = httpAcceptEncoding(value, 0, toI32(value.length), HTTP_OFFER_GZIP);
|
|
14
|
+
* const m: i32 = enc.compress(coding, body, 0, n);
|
|
15
|
+
* if (m >= 0) {
|
|
16
|
+
* enc.addFields(names, values);
|
|
17
|
+
* h2.respond(id, 200, enc.names, enc.values, false);
|
|
18
|
+
* h2.write(id, enc.output, 0, m);
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* **Opt-in.** Nothing here runs unless the program asks: it decides which
|
|
22
|
+
* responses to compress, and `HttpCompressor` declines any body shorter than
|
|
23
|
+
* its `minLength`, longer than its `maxLength`, or that gzip would not make
|
|
24
|
+
* smaller, answering -1 so the program sends the bytes as they are.
|
|
25
|
+
*
|
|
26
|
+
* **Negotiation** (`httpAcceptEncoding`) follows §12.5.3: each listed coding
|
|
27
|
+
* with its q-value, `x-gzip` as `gzip`, `*` for every coding not listed, and
|
|
28
|
+
* `identity` acceptable unless it is given q=0, directly or through `*`. Of
|
|
29
|
+
* the codings the program offers, the most preferred with q above 0 wins, the
|
|
30
|
+
* program's order (gzip, then deflate) breaking ties; it beats `identity` at
|
|
31
|
+
* an equal q, and beats an `identity` the field does not mention at any q. With no field at all the answer is
|
|
32
|
+
* `HTTP_CODING_IDENTITY` (the RFC allows any coding then, but a client that
|
|
33
|
+
* says nothing is safest sent nothing it may not read); an empty field asks
|
|
34
|
+
* for identity too. `HTTP_CODING_NONE` means nothing offered is acceptable
|
|
35
|
+
* and identity is refused: a server may answer 406 or send identity anyway.
|
|
36
|
+
* A malformed element is skipped. The parser allocates nothing.
|
|
37
|
+
*
|
|
38
|
+
* **Compressing allocates nothing**: `HttpCompressor` holds a
|
|
39
|
+
* `GzipCompressor`, an output buffer of `compressBound(maxLength)` bytes and
|
|
40
|
+
* the field arrays `addFields` fills, all built once.
|
|
41
|
+
* `HTTP_CODING_DEFLATE` (zlib framing) is negotiated but not produced: a
|
|
42
|
+
* client that accepts only `deflate` is sent identity, which every client
|
|
43
|
+
* reads.
|
|
44
|
+
*/
|
|
45
|
+
import { DEFLATE_FAST, compressBound } from "nish/compress/deflate"
|
|
46
|
+
import { GzipCompressor } from "nish/compress/gzip"
|
|
47
|
+
|
|
48
|
+
/** No content coding: the body as it is. */
|
|
49
|
+
export const HTTP_CODING_IDENTITY: i32 = 0
|
|
50
|
+
|
|
51
|
+
/** `gzip` (RFC 9110 §8.4.1.3), or its alias `x-gzip`. */
|
|
52
|
+
export const HTTP_CODING_GZIP: i32 = 1
|
|
53
|
+
|
|
54
|
+
/** `deflate`: the zlib format (RFC 9110 §8.4.1.2). */
|
|
55
|
+
export const HTTP_CODING_DEFLATE: i32 = 2
|
|
56
|
+
|
|
57
|
+
/** Nothing offered is acceptable, identity included (§12.5.3: 406, or identity anyway). */
|
|
58
|
+
export const HTTP_CODING_NONE: i32 = -1
|
|
59
|
+
|
|
60
|
+
/** `httpAcceptEncoding`'s `offered` bits: the program can send gzip, deflate. */
|
|
61
|
+
export const HTTP_OFFER_GZIP: i32 = 1
|
|
62
|
+
export const HTTP_OFFER_DEFLATE: i32 = 2
|
|
63
|
+
|
|
64
|
+
/** A q-value of 1, in thousandths. */
|
|
65
|
+
const HTTP_Q_ONE: i32 = 1000
|
|
66
|
+
|
|
67
|
+
/** Whether `c` is an ASCII letter, digit or one of the token characters a coding uses. */
|
|
68
|
+
const httpCodingChar = (c: i32): boolean =>
|
|
69
|
+
(c >= 97 && c <= 122) ||
|
|
70
|
+
(c >= 65 && c <= 90) ||
|
|
71
|
+
(c >= 48 && c <= 57) ||
|
|
72
|
+
c === 45 ||
|
|
73
|
+
c === 46 ||
|
|
74
|
+
c === 95 ||
|
|
75
|
+
c === 42 ||
|
|
76
|
+
c === 33 ||
|
|
77
|
+
c === 35 ||
|
|
78
|
+
c === 36 ||
|
|
79
|
+
c === 37 ||
|
|
80
|
+
c === 38 ||
|
|
81
|
+
c === 39 ||
|
|
82
|
+
c === 43 ||
|
|
83
|
+
c === 94 ||
|
|
84
|
+
c === 96 ||
|
|
85
|
+
c === 124 ||
|
|
86
|
+
c === 126
|
|
87
|
+
|
|
88
|
+
/** Whether `buf[start .. end)` is `word`, ignoring ASCII case; `word` is lower case. */
|
|
89
|
+
const httpCodingIs = (buf: u8[], start: i32, end: i32, word: string): boolean => {
|
|
90
|
+
if (end - start !== toI32(word.length)) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
for (let i: i32 = 0; i < end - start && i < toI32(word.length); i += 1) {
|
|
94
|
+
let c: i32 = toI32(buf[start + i])
|
|
95
|
+
if (c >= 65 && c <= 90) {
|
|
96
|
+
c += 32
|
|
97
|
+
}
|
|
98
|
+
if (c !== toI32(word.charCodeAt(i))) {
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The q-value of `buf[start .. end)`, in thousandths (RFC 9110 §12.4.2:
|
|
107
|
+
* `0`, `0.` and up to three digits, `1`, `1.` and up to three zeros), or -1
|
|
108
|
+
* when it is not one.
|
|
109
|
+
*/
|
|
110
|
+
const httpQValue = (buf: u8[], start: i32, end: i32): i32 => {
|
|
111
|
+
if (start >= end) {
|
|
112
|
+
return -1
|
|
113
|
+
}
|
|
114
|
+
const lead: i32 = toI32(buf[start])
|
|
115
|
+
if (lead !== 48 && lead !== 49) {
|
|
116
|
+
return -1
|
|
117
|
+
}
|
|
118
|
+
let q: i32 = lead === 49 ? HTTP_Q_ONE : 0
|
|
119
|
+
if (start + 1 === end) {
|
|
120
|
+
return q
|
|
121
|
+
}
|
|
122
|
+
if (buf[start + 1] !== 46 || end - start > 5) {
|
|
123
|
+
return -1
|
|
124
|
+
}
|
|
125
|
+
let scale: i32 = 100
|
|
126
|
+
for (let i: i32 = start + 2; i < end && i >= 0 && i < toI32(buf.length); i += 1) {
|
|
127
|
+
const d: i32 = toI32(buf[i]) - 48
|
|
128
|
+
if (d < 0 || d > 9 || (lead === 49 && d !== 0)) {
|
|
129
|
+
return -1
|
|
130
|
+
}
|
|
131
|
+
q += d * scale
|
|
132
|
+
scale = scale / 10
|
|
133
|
+
}
|
|
134
|
+
return q
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** A coding's q: its own when listed, else `*`'s when that is, else 0. */
|
|
138
|
+
const httpQOrStar = (own: i32, star: i32): i32 => {
|
|
139
|
+
if (own >= 0) {
|
|
140
|
+
return own
|
|
141
|
+
}
|
|
142
|
+
return star >= 0 ? star : 0
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Whether `c` is optional whitespace (SP or HTAB). */
|
|
146
|
+
const httpOws = (c: i32): boolean => c === 32 || c === 9
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The content coding to send for the `Accept-Encoding` field value
|
|
150
|
+
* `buf[start .. end)` among the codings `offered` (`HTTP_OFFER_GZIP |
|
|
151
|
+
* HTTP_OFFER_DEFLATE`): `HTTP_CODING_GZIP`, `HTTP_CODING_DEFLATE`,
|
|
152
|
+
* `HTTP_CODING_IDENTITY` or `HTTP_CODING_NONE`, by the rules in the module
|
|
153
|
+
* comment. A window outside `buf` panics.
|
|
154
|
+
*/
|
|
155
|
+
export const httpAcceptEncoding = (buf: u8[], start: i32, end: i32, offered: i32): i32 => {
|
|
156
|
+
if (start < 0 || start > end || end > toI32(buf.length)) {
|
|
157
|
+
panic("httpAcceptEncoding: the window lies outside its buffer")
|
|
158
|
+
}
|
|
159
|
+
let qGzip: i32 = -1
|
|
160
|
+
let qDeflate: i32 = -1
|
|
161
|
+
let qIdentity: i32 = -1
|
|
162
|
+
let qStar: i32 = -1
|
|
163
|
+
let p: i32 = start
|
|
164
|
+
while (p < end) {
|
|
165
|
+
// One element: OWS coding OWS *( ";" OWS name "=" value ) OWS ","
|
|
166
|
+
while (p < end && (httpOws(toI32(buf[p])) || buf[p] === 44)) {
|
|
167
|
+
p += 1
|
|
168
|
+
}
|
|
169
|
+
const codingStart: i32 = p
|
|
170
|
+
while (p < end && httpCodingChar(toI32(buf[p]))) {
|
|
171
|
+
p += 1
|
|
172
|
+
}
|
|
173
|
+
const codingEnd: i32 = p
|
|
174
|
+
let q: i32 = HTTP_Q_ONE
|
|
175
|
+
let valid: boolean = codingEnd > codingStart
|
|
176
|
+
while (p < end && buf[p] !== 44) {
|
|
177
|
+
while (p < end && httpOws(toI32(buf[p]))) {
|
|
178
|
+
p += 1
|
|
179
|
+
}
|
|
180
|
+
if (p >= end || buf[p] === 44) {
|
|
181
|
+
break
|
|
182
|
+
}
|
|
183
|
+
if (buf[p] !== 59) {
|
|
184
|
+
valid = false
|
|
185
|
+
while (p < end && buf[p] !== 44) {
|
|
186
|
+
p += 1
|
|
187
|
+
}
|
|
188
|
+
break
|
|
189
|
+
}
|
|
190
|
+
p += 1
|
|
191
|
+
while (p < end && httpOws(toI32(buf[p]))) {
|
|
192
|
+
p += 1
|
|
193
|
+
}
|
|
194
|
+
const nameStart: i32 = p
|
|
195
|
+
while (p < end && httpCodingChar(toI32(buf[p]))) {
|
|
196
|
+
p += 1
|
|
197
|
+
}
|
|
198
|
+
const nameEnd: i32 = p
|
|
199
|
+
if (p >= end || buf[p] !== 61) {
|
|
200
|
+
valid = false
|
|
201
|
+
continue
|
|
202
|
+
}
|
|
203
|
+
p += 1
|
|
204
|
+
const valueStart: i32 = p
|
|
205
|
+
while (p < end && httpCodingChar(toI32(buf[p]))) {
|
|
206
|
+
p += 1
|
|
207
|
+
}
|
|
208
|
+
if (httpCodingIs(buf, nameStart, nameEnd, "q")) {
|
|
209
|
+
q = httpQValue(buf, valueStart, p)
|
|
210
|
+
if (q < 0) {
|
|
211
|
+
valid = false
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (valid) {
|
|
216
|
+
if (
|
|
217
|
+
httpCodingIs(buf, codingStart, codingEnd, "gzip") ||
|
|
218
|
+
httpCodingIs(buf, codingStart, codingEnd, "x-gzip")
|
|
219
|
+
) {
|
|
220
|
+
qGzip = q
|
|
221
|
+
} else if (httpCodingIs(buf, codingStart, codingEnd, "deflate")) {
|
|
222
|
+
qDeflate = q
|
|
223
|
+
} else if (httpCodingIs(buf, codingStart, codingEnd, "identity")) {
|
|
224
|
+
qIdentity = q
|
|
225
|
+
} else if (httpCodingIs(buf, codingStart, codingEnd, "*")) {
|
|
226
|
+
qStar = q
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const gzip: i32 = (offered & HTTP_OFFER_GZIP) === 0 ? 0 : httpQOrStar(qGzip, qStar)
|
|
231
|
+
const deflate: i32 = (offered & HTTP_OFFER_DEFLATE) === 0 ? 0 : httpQOrStar(qDeflate, qStar)
|
|
232
|
+
// `identity` unlisted (and not reached by `*`) is acceptable but stated no
|
|
233
|
+
// preference, so any offered coding with q above 0 is sent before it.
|
|
234
|
+
let identity: i32 = -1
|
|
235
|
+
if (qIdentity >= 0) {
|
|
236
|
+
identity = qIdentity
|
|
237
|
+
} else if (qStar >= 0) {
|
|
238
|
+
identity = qStar
|
|
239
|
+
}
|
|
240
|
+
let coding: i32 = HTTP_CODING_NONE
|
|
241
|
+
let codingQ: i32 = 0
|
|
242
|
+
if (deflate > gzip) {
|
|
243
|
+
coding = HTTP_CODING_DEFLATE
|
|
244
|
+
codingQ = deflate
|
|
245
|
+
} else if (gzip > 0) {
|
|
246
|
+
coding = HTTP_CODING_GZIP
|
|
247
|
+
codingQ = gzip
|
|
248
|
+
}
|
|
249
|
+
if (coding !== HTTP_CODING_NONE && codingQ >= identity) {
|
|
250
|
+
return coding
|
|
251
|
+
}
|
|
252
|
+
if (identity !== 0) {
|
|
253
|
+
return HTTP_CODING_IDENTITY
|
|
254
|
+
}
|
|
255
|
+
return HTTP_CODING_NONE
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** The bytes of an ASCII string. */
|
|
259
|
+
const httpCompressBytes = (text: string): u8[] => {
|
|
260
|
+
const out: u8[] = new Array<u8>(toI32(text.length))
|
|
261
|
+
for (let i: i32 = 0; i < toI32(text.length) && i < toI32(out.length); i += 1) {
|
|
262
|
+
out[i] = toU8(text.charCodeAt(i))
|
|
263
|
+
}
|
|
264
|
+
return out
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Compresses response bodies with gzip into a buffer of its own, and builds
|
|
269
|
+
* the response fields that say so. One per thread; allocated once.
|
|
270
|
+
*/
|
|
271
|
+
export class HttpCompressor {
|
|
272
|
+
readonly gzip: GzipCompressor
|
|
273
|
+
/** Where `compress` writes; valid until the next call. */
|
|
274
|
+
readonly output: u8[]
|
|
275
|
+
/** The fields `addFields` built: the program's, then `Content-Encoding` and `Vary`. */
|
|
276
|
+
readonly names: u8[][]
|
|
277
|
+
readonly values: u8[][]
|
|
278
|
+
readonly contentEncodingName: u8[]
|
|
279
|
+
readonly gzipValue: u8[]
|
|
280
|
+
readonly varyName: u8[]
|
|
281
|
+
readonly acceptEncodingValue: u8[]
|
|
282
|
+
/** The shortest body worth compressing, and the longest the output can hold. */
|
|
283
|
+
readonly minLength: i32
|
|
284
|
+
readonly maxLength: i32
|
|
285
|
+
/**
|
|
286
|
+
* Whether `addFields` adds `Vary: Accept-Encoding` (RFC 9110 §12.5.5), which
|
|
287
|
+
* a cache needs whenever the same resource may be sent either way. On by
|
|
288
|
+
* default; turn it off when the program sets its own `Vary`.
|
|
289
|
+
*/
|
|
290
|
+
vary: boolean
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* A compressor at `level` (`DEFLATE_FAST` suits a server) for bodies of
|
|
294
|
+
* `minLength` to `maxLength` bytes. A level outside 0 to 9, a negative
|
|
295
|
+
* `minLength` or a `maxLength` below it panics.
|
|
296
|
+
*/
|
|
297
|
+
constructor(level: i32, minLength: i32, maxLength: i32) {
|
|
298
|
+
if (minLength < 0 || maxLength < minLength) {
|
|
299
|
+
panic("HttpCompressor: the lengths are out of order")
|
|
300
|
+
}
|
|
301
|
+
this.gzip = new GzipCompressor(level)
|
|
302
|
+
this.output = new Array<u8>(compressBound(maxLength))
|
|
303
|
+
this.names = []
|
|
304
|
+
this.values = []
|
|
305
|
+
this.contentEncodingName = httpCompressBytes("content-encoding")
|
|
306
|
+
this.gzipValue = httpCompressBytes("gzip")
|
|
307
|
+
this.varyName = httpCompressBytes("vary")
|
|
308
|
+
this.acceptEncodingValue = httpCompressBytes("accept-encoding")
|
|
309
|
+
this.minLength = minLength
|
|
310
|
+
this.maxLength = maxLength
|
|
311
|
+
this.vary = true
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Compresses `body[off .. off + len)` into `output` when `coding` is
|
|
316
|
+
* `HTTP_CODING_GZIP`, the length is in `[minLength, maxLength]` and gzip
|
|
317
|
+
* makes it smaller; answers the compressed length, or -1 to send the body
|
|
318
|
+
* as it is. A window outside `body` panics.
|
|
319
|
+
*/
|
|
320
|
+
compress(coding: i32, body: u8[], off: i32, len: i32): i32 {
|
|
321
|
+
if (off < 0 || len < 0 || off > toI32(body.length) - len) {
|
|
322
|
+
panic("HttpCompressor.compress: the window lies outside its body")
|
|
323
|
+
}
|
|
324
|
+
if (coding !== HTTP_CODING_GZIP || len < this.minLength || len > this.maxLength) {
|
|
325
|
+
return -1
|
|
326
|
+
}
|
|
327
|
+
const n: i32 = this.gzip.compress(body, off, len, this.output, toI32(0))
|
|
328
|
+
if (n < 0 || n >= len) {
|
|
329
|
+
return -1
|
|
330
|
+
}
|
|
331
|
+
return n
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Sets `names` / `values` to the program's fields followed by
|
|
336
|
+
* `Content-Encoding: gzip` and, when `vary`, `Vary: Accept-Encoding`. The
|
|
337
|
+
* arrays are reused, so after the first few calls this allocates nothing;
|
|
338
|
+
* they hold until the next call.
|
|
339
|
+
*/
|
|
340
|
+
addFields(names: u8[][], values: u8[][]): void {
|
|
341
|
+
while (this.names.length > 0) {
|
|
342
|
+
this.names.pop()
|
|
343
|
+
}
|
|
344
|
+
while (this.values.length > 0) {
|
|
345
|
+
this.values.pop()
|
|
346
|
+
}
|
|
347
|
+
for (let i: i32 = 0; i < toI32(values.length); i += 1) {
|
|
348
|
+
if (i < toI32(names.length)) {
|
|
349
|
+
const name: u8[] = names[i]
|
|
350
|
+
const value: u8[] = values[i]
|
|
351
|
+
this.names.push(name)
|
|
352
|
+
this.values.push(value)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
this.names.push(this.contentEncodingName)
|
|
356
|
+
this.values.push(this.gzipValue)
|
|
357
|
+
this.addVary()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Appends `Vary: Accept-Encoding` to the arrays `addFields` built when `vary` is set. */
|
|
361
|
+
addVary(): void {
|
|
362
|
+
if (this.vary) {
|
|
363
|
+
this.names.push(this.varyName)
|
|
364
|
+
this.values.push(this.acceptEncodingValue)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Sets `names` / `values` to the program's fields and, when `vary`,
|
|
370
|
+
* `Vary: Accept-Encoding`: the fields of a body sent as it is from a
|
|
371
|
+
* resource that is sometimes compressed.
|
|
372
|
+
*/
|
|
373
|
+
identityFields(names: u8[][], values: u8[][]): void {
|
|
374
|
+
while (this.names.length > 0) {
|
|
375
|
+
this.names.pop()
|
|
376
|
+
}
|
|
377
|
+
while (this.values.length > 0) {
|
|
378
|
+
this.values.pop()
|
|
379
|
+
}
|
|
380
|
+
for (let i: i32 = 0; i < toI32(values.length); i += 1) {
|
|
381
|
+
if (i < toI32(names.length)) {
|
|
382
|
+
const name: u8[] = names[i]
|
|
383
|
+
const value: u8[] = values[i]
|
|
384
|
+
this.names.push(name)
|
|
385
|
+
this.values.push(value)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
this.addVary()
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/** A compressor for the usual server: `DEFLATE_FAST`, bodies of 1 KB to 1 MB. */
|
|
393
|
+
export const httpCompressorDefault = (): HttpCompressor => new HttpCompressor(DEFLATE_FAST, 1024, 1048576)
|