@dooboostore/simple-boot-http-server 1.0.33 → 1.0.35

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.
@@ -28621,6 +28621,7 @@ var ReqHeader = class {
28621
28621
  var import_node_gzip = __toESM(require_dist(), 1);
28622
28622
  import { createGzip, constants as zlibConstants } from "zlib";
28623
28623
  import { Blob as Blob3 } from "node:buffer";
28624
+ var resEndingSet = /* @__PURE__ */ new WeakSet();
28624
28625
  var RequestResponse = class _RequestResponse {
28625
28626
  constructor(req, res, config) {
28626
28627
  // [아키텍트님의 정석] RequestResponse 객체 고유의 속성 저장소 (트랜잭션 생명주기)
@@ -28997,6 +28998,9 @@ var RequestResponse = class _RequestResponse {
28997
28998
  return this.createRequestResponseChain(this.res.statusCode);
28998
28999
  }
28999
29000
  resWrite(chunk, encoding = "utf8") {
29001
+ if (chunk === void 0) {
29002
+ return this.createRequestResponseChain(this.resWriteChunk);
29003
+ }
29000
29004
  this.resWriteChunk = chunk;
29001
29005
  return this.createRequestResponseChain(this.resWriteChunk);
29002
29006
  }
@@ -29031,31 +29035,42 @@ var RequestResponse = class _RequestResponse {
29031
29035
  this.res.end(data);
29032
29036
  }
29033
29037
  async resEnd(chunk) {
29034
- if (chunk instanceof Response) {
29035
- chunk.headers.forEach((value, key) => {
29036
- this.res.setHeader(`ORIGIN-${key}`, value);
29037
- });
29038
- if (!this.resHeader(HttpHeaders.ContentType)) {
29039
- const contentType = chunk.headers.get(HttpHeaders.ContentType);
29040
- if (contentType) this.res.setHeader(HttpHeaders.ContentType, contentType);
29041
- }
29042
- this.res.statusCode = chunk.status;
29043
- this.resWriteChunk = Buffer2.from(await chunk.arrayBuffer());
29044
- } else if (chunk instanceof Blob3) {
29045
- this.resWriteChunk = Buffer2.from(await chunk.arrayBuffer());
29046
- if (!this.resHeader(HttpHeaders.ContentType)) {
29047
- this.res.setHeader(HttpHeaders.ContentType, chunk.type);
29048
- }
29049
- } else if (chunk instanceof ArrayBuffer) {
29050
- this.resWriteChunk = Buffer2.from(chunk);
29051
- } else {
29052
- this.resWriteChunk = chunk ?? this.resWriteChunk;
29038
+ if (resEndingSet.has(this.res) || this.resIsDone()) {
29039
+ return;
29053
29040
  }
29054
- if (this.req.readable) {
29055
- await this.reqBodyData();
29056
- await this.resEndChunk();
29057
- } else {
29058
- await this.resEndChunk();
29041
+ resEndingSet.add(this.res);
29042
+ try {
29043
+ if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(chunk) && !Buffer2.isBuffer(chunk)) {
29044
+ const view = chunk;
29045
+ this.resWriteChunk = Buffer2.from(view.buffer, view.byteOffset, view.byteLength);
29046
+ } else if (chunk instanceof Response) {
29047
+ chunk.headers.forEach((value, key) => {
29048
+ this.res.setHeader(`ORIGIN-${key}`, value);
29049
+ });
29050
+ if (!this.resHeader(HttpHeaders.ContentType)) {
29051
+ const contentType = chunk.headers.get(HttpHeaders.ContentType);
29052
+ if (contentType) this.res.setHeader(HttpHeaders.ContentType, contentType);
29053
+ }
29054
+ this.res.statusCode = chunk.status;
29055
+ this.resWriteChunk = Buffer2.from(await chunk.arrayBuffer());
29056
+ } else if (chunk instanceof Blob3) {
29057
+ this.resWriteChunk = Buffer2.from(await chunk.arrayBuffer());
29058
+ if (!this.resHeader(HttpHeaders.ContentType)) {
29059
+ this.res.setHeader(HttpHeaders.ContentType, chunk.type);
29060
+ }
29061
+ } else if (chunk instanceof ArrayBuffer) {
29062
+ this.resWriteChunk = Buffer2.from(chunk);
29063
+ } else {
29064
+ this.resWriteChunk = chunk ?? this.resWriteChunk;
29065
+ }
29066
+ if (this.req.readable) {
29067
+ await this.reqBodyData();
29068
+ await this.resEndChunk();
29069
+ } else {
29070
+ await this.resEndChunk();
29071
+ }
29072
+ } finally {
29073
+ resEndingSet.delete(this.res);
29059
29074
  }
29060
29075
  }
29061
29076
  resRedirect(statusCode, location) {
@@ -29388,6 +29403,26 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29388
29403
  this.webSocketClients = /* @__PURE__ */ new Map();
29389
29404
  this.sessionManager = new SessionManager(this.option);
29390
29405
  }
29406
+ /**
29407
+ * Final response flush that can never escape as an unhandled rejection.
29408
+ * When the response is already gone (sent, closed, or destroyed mid-write),
29409
+ * there is nobody left to send to, so gone-response write errors
29410
+ * (ERR_HTTP_HEADERS_SENT, ERR_STREAM_ALREADY_FINISHED,
29411
+ * ERR_STREAM_DESTROYED, ECONNRESET) are swallowed; anything else still throws.
29412
+ */
29413
+ async safeResEnd(rr) {
29414
+ if (rr.resIsDone()) {
29415
+ return;
29416
+ }
29417
+ try {
29418
+ await rr.resEnd();
29419
+ } catch (e) {
29420
+ const code = e && (e.code || "");
29421
+ if (code !== "ERR_HTTP_HEADERS_SENT" && code !== "ERR_STREAM_ALREADY_FINISHED" && code !== "ERR_STREAM_DESTROYED" && code !== "ECONNRESET") {
29422
+ throw e;
29423
+ }
29424
+ }
29425
+ }
29391
29426
  run(otherInstanceSim) {
29392
29427
  otherInstanceSim ??= /* @__PURE__ */ new Map();
29393
29428
  otherInstanceSim.set(_SimpleBootHttpServer, this);
@@ -29430,7 +29465,7 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29430
29465
  }
29431
29466
  }
29432
29467
  if (!rr.resIsDone()) {
29433
- rr.resEnd();
29468
+ await this.safeResEnd(rr);
29434
29469
  }
29435
29470
  });
29436
29471
  res.on("error", async () => {
@@ -29447,7 +29482,7 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29447
29482
  }
29448
29483
  }
29449
29484
  if (!rr.resIsDone()) {
29450
- rr.resEnd();
29485
+ await this.safeResEnd(rr);
29451
29486
  }
29452
29487
  });
29453
29488
  const rr = new RequestResponse(req, res, { sessionManager: this.sessionManager, option: this.option });
@@ -29642,14 +29677,15 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29642
29677
  headers[HttpHeaders.ContentType] = contentType;
29643
29678
  }
29644
29679
  rr.resSetHeaders(headers);
29645
- rr.resSetStatusCode(resConfig?.status ?? 200 /* Ok */);
29680
+ if (resConfig?.status !== void 0) {
29681
+ rr.resSetStatusCode(resConfig.status);
29682
+ }
29646
29683
  await rr.resStream(data, { compress: stream?.compress });
29647
29684
  } else {
29648
29685
  if (it.config?.resolver) {
29649
29686
  const execute = typeof it.config.resolver === "function" ? this.simstanceManager.getOrNewSim({ target: it.config.resolver }) : it.config.resolver;
29650
29687
  data = await execute?.resolve?.(data, rr, resConfig);
29651
29688
  }
29652
- const status = resConfig?.status ?? 200 /* Ok */;
29653
29689
  const headers = resConfig?.header ?? {};
29654
29690
  if (resConfig?.contentType) {
29655
29691
  headers[HttpHeaders.ContentType] = resConfig.contentType;
@@ -29660,7 +29696,9 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29660
29696
  data = JSON.stringify(data);
29661
29697
  }
29662
29698
  rr.resSetHeaders(headers);
29663
- rr.resSetStatusCode(status);
29699
+ if (resConfig?.status !== void 0) {
29700
+ rr.resSetStatusCode(resConfig.status);
29701
+ }
29664
29702
  rr.resWrite(data);
29665
29703
  }
29666
29704
  }
@@ -29702,7 +29740,7 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29702
29740
  transactionManager?.finally();
29703
29741
  }
29704
29742
  if (!rr.resIsDone()) {
29705
- rr.resEnd();
29743
+ await this.safeResEnd(rr);
29706
29744
  }
29707
29745
  });
29708
29746
  if (this.option.webSocketEndPoints) {