@amritk/nish-x86_64-linux 0.26.0 → 0.28.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.
@@ -115,7 +115,9 @@
115
115
  import { Secret } from "nish:secret"
116
116
  import { copyBytes } from "nish/bytes"
117
117
  import {
118
+ HTTP_CODING_GZIP,
118
119
  HTTP_CODING_IDENTITY,
120
+ HTTP_CODING_NONE,
119
121
  HTTP_OFFER_GZIP,
120
122
  HttpCompressor,
121
123
  httpAcceptEncoding,
@@ -559,6 +561,11 @@ export class Http1Connection {
559
561
  inputEnded: boolean = false
560
562
  /** A head has begun to arrive and is not read whole yet: `headSince` is its deadline's start. */
561
563
  headTimed: boolean = false
564
+ /**
565
+ * This connection's TCP maximum segment size, for `respondEncoded` under
566
+ * `HttpCompressor.segmentMode`; 0, the default, uses the compressor's `mss`.
567
+ */
568
+ mss: i32 = 0
562
569
 
563
570
  /** A connection under `config`. A cap outside what the connection can work with panics. */
564
571
  constructor(config: Http1Config) {
@@ -1221,6 +1228,19 @@ export class Http1Connection {
1221
1228
  * gzip. Allocates nothing.
1222
1229
  */
1223
1230
  acceptEncoding(): i32 {
1231
+ return this.acceptEncodingOf(HTTP_OFFER_GZIP)
1232
+ }
1233
+
1234
+ /**
1235
+ * Whether the current request's `Accept-Encoding` refuses the body as it
1236
+ * is (`httpIdentityRefused`); `respondEncoded` then gzips any body it can.
1237
+ */
1238
+ identityRefused(): boolean {
1239
+ return this.acceptEncodingOf(toI32(0)) === HTTP_CODING_NONE
1240
+ }
1241
+
1242
+ /** `httpAcceptEncoding` of the current request's `Accept-Encoding`, with `offered`. */
1243
+ acceptEncodingOf(offered: i32): i32 {
1224
1244
  const parser: Http1Parser = this.parser
1225
1245
  const i: i32 = parser.headerIndex("accept-encoding")
1226
1246
  const spans: i32[] = parser.spans
@@ -1232,7 +1252,7 @@ export class Http1Connection {
1232
1252
  if (start < 0 || start > end || end > toI32(parser.head.length)) {
1233
1253
  return HTTP_CODING_IDENTITY
1234
1254
  }
1235
- return httpAcceptEncoding(parser.head, start, end, HTTP_OFFER_GZIP)
1255
+ return httpAcceptEncoding(parser.head, start, end, offered)
1236
1256
  }
1237
1257
 
1238
1258
  /**
@@ -1240,9 +1260,15 @@ export class Http1Connection {
1240
1260
  * call: `respond`, `write` and `end`, the body compressed by `enc` when
1241
1261
  * `coding` (from `acceptEncoding`) is gzip and `enc.compress` takes it,
1242
1262
  * with `Content-Encoding: gzip` and the compressed `Content-Length`, and
1243
- * otherwise sent as it is; `Vary: Accept-Encoding` either way while
1244
- * `enc.vary` is set. The program's fields may not name `Content-Encoding`
1245
- * or, with `enc.vary`, `Vary`. The whole response is written or none of
1263
+ * otherwise sent as it is; `Vary: Accept-Encoding` while `enc.vary` is set
1264
+ * and the choice turned on the request (`HttpCompressor.varies`). Under
1265
+ * `enc.segmentMode` the compressed response goes out only when, head
1266
+ * included, it takes fewer segments of `mss` bytes (this connection's, or
1267
+ * `enc.mss`) than the body as it is; `enc.decision` says what was chosen.
1268
+ * A request that refuses identity (`identityRefused`) is sent gzip whatever
1269
+ * the length, the saving or the segments (`enc.compressAnyway`).
1270
+ * The program's fields may not name `Content-Encoding` or, with
1271
+ * `enc.vary`, `Vary`. The whole response is written or none of
1246
1272
  * it: `H1_AGAIN` when the output has no room for it yet (`H1_WRITE` says
1247
1273
  * when to try again, compressing again), `H1_INVALID` for a response
1248
1274
  * larger than the output could ever hold or one `respond` refuses,
@@ -1263,7 +1289,10 @@ export class Http1Connection {
1263
1289
  if (!this.answerable()) {
1264
1290
  return H1_CLOSED
1265
1291
  }
1266
- const packed: i32 = enc.compress(coding, body, off, len)
1292
+ const required: boolean = coding === HTTP_CODING_GZIP && this.identityRefused()
1293
+ let packed: i32 = required
1294
+ ? enc.compressAnyway(coding, body, off, len)
1295
+ : enc.compress(coding, body, off, len)
1267
1296
  let n: i32 = len
1268
1297
  if (packed >= 0) {
1269
1298
  enc.addFields(names, values)
@@ -1278,18 +1307,28 @@ export class Http1Connection {
1278
1307
  this.room()
1279
1308
  const outputEnd: i32 = this.outputEnd
1280
1309
  const closeAfter: boolean = this.closeAfter
1281
- const r: i32 = this.respond(status, enc.names, enc.values, n)
1310
+ let r: i32 = this.respond(status, enc.names, enc.values, n)
1282
1311
  if (r !== 0) {
1283
1312
  return r
1284
1313
  }
1314
+ if (packed >= 0 && enc.segmentMode && !required) {
1315
+ // The head just written, and the one the body as it is would get.
1316
+ const head: i32 = this.outputEnd - outputEnd
1317
+ const plain: i32 = enc.http1IdentityHead(head, packed, len)
1318
+ if (!enc.fewerSegments(plain + len, head + packed, this.mss)) {
1319
+ this.unrespond(outputEnd, closeAfter)
1320
+ enc.identityFields(names, values)
1321
+ packed = -1
1322
+ n = len
1323
+ r = this.respond(status, enc.names, enc.values, n)
1324
+ if (r !== 0) {
1325
+ return r
1326
+ }
1327
+ }
1328
+ }
1285
1329
  if (!this.responseEmpty && n > this.bodyRoom()) {
1286
1330
  const fits: boolean = this.outputEnd - outputEnd + n <= this.config.outputSize - H1_CONTROL_RESERVE
1287
- this.outputEnd = outputEnd
1288
- this.closeAfter = closeAfter
1289
- this.response = H1_R_NONE
1290
- this.responseFraming = 0
1291
- this.responseLeft = 0
1292
- this.responseEmpty = false
1331
+ this.unrespond(outputEnd, closeAfter)
1293
1332
  if (!fits) {
1294
1333
  return H1_INVALID
1295
1334
  }
@@ -1303,6 +1342,16 @@ export class Http1Connection {
1303
1342
  return this.end()
1304
1343
  }
1305
1344
 
1345
+ /** Takes back a head `respond` just queued: `outputEnd` and `closeAfter` as they were before it. */
1346
+ unrespond(outputEnd: i32, closeAfter: boolean): void {
1347
+ this.outputEnd = outputEnd
1348
+ this.closeAfter = closeAfter
1349
+ this.response = H1_R_NONE
1350
+ this.responseFraming = 0
1351
+ this.responseLeft = 0
1352
+ this.responseEmpty = false
1353
+ }
1354
+
1306
1355
  // ---- WebSocket ----------------------------------------------------------------
1307
1356
 
1308
1357
  /**