hbsig 0.1.4 → 0.2.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/cjs/httpsig.js CHANGED
@@ -5,10 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.httpsig_from = httpsig_from;
7
7
  exports.httpsig_to = httpsig_to;
8
+ exports.structured_from = structured_from;
9
+ exports.structured_to = structured_to;
8
10
  var _crypto = _interopRequireDefault(require("crypto"));
9
11
  var _flat = require("./flat.js");
10
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
11
- function _toArray(r) { return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest(); }
12
13
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
13
14
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
15
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
@@ -342,7 +343,22 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
342
343
  return "";
343
344
  }
344
345
 
345
- // Parse multipart body
346
+ // Helper to detect if a string contains binary data
347
+ function isBinaryData(str) {
348
+ // Check first 100 chars for binary indicators
349
+ for (var i = 0; i < Math.min(str.length, 100); i++) {
350
+ var code = str.charCodeAt(i);
351
+ // Non-printable chars (except CR/LF/TAB)
352
+ if (code < 32 && code !== 9 && code !== 10 && code !== 13) return true;
353
+ // High byte range that's not valid text
354
+ if (code > 126 && code < 160) return true;
355
+ // Null byte is definitely binary
356
+ if (code === 0) return true;
357
+ }
358
+ return false;
359
+ }
360
+
361
+ // Parse multipart body - handles binary data in headers
346
362
  function parseMultipart(contentType, body) {
347
363
  var boundaryMatch = contentType.match(/boundary="?([^";\s]+)"?/);
348
364
  if (!boundaryMatch) return {};
@@ -350,8 +366,8 @@ function parseMultipart(contentType, body) {
350
366
  var boundaryDelim = "--".concat(boundary);
351
367
  var endBoundary = "--".concat(boundary, "--");
352
368
 
353
- // Remove the final boundary terminator if present
354
- var bodyContent = body;
369
+ // Use binary encoding to preserve all bytes as character codes 0-255
370
+ var bodyContent = typeof body === "string" ? body : body.toString("binary");
355
371
  if (bodyContent.endsWith(endBoundary)) {
356
372
  bodyContent = bodyContent.substring(0, bodyContent.lastIndexOf(endBoundary));
357
373
  }
@@ -365,59 +381,137 @@ function parseMultipart(contentType, body) {
365
381
  try {
366
382
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
367
383
  var part = _step3.value;
368
- var _part$split = part.split(DOUBLE_CRLF),
369
- _part$split2 = _toArray(_part$split),
370
- headerBlock = _part$split2[0],
371
- bodyParts = _part$split2.slice(1);
372
- var partBody = bodyParts.join(DOUBLE_CRLF);
373
-
374
- // Remove trailing CRLF
375
- partBody = partBody.replace(/\r?\n?$/, "");
384
+ // First split to find the headers/body boundary (double CRLF)
385
+ var headerBodySplit = part.indexOf(DOUBLE_CRLF);
386
+ var headerBlock = void 0,
387
+ partBody = void 0;
388
+ if (headerBodySplit !== -1) {
389
+ headerBlock = part.substring(0, headerBodySplit);
390
+ partBody = part.substring(headerBodySplit + DOUBLE_CRLF.length);
391
+ // Remove trailing CRLF from body
392
+ partBody = partBody.replace(/\r?\n?$/, "");
393
+ } else {
394
+ headerBlock = part;
395
+ partBody = "";
396
+ }
376
397
  var headers = {};
377
- var headerLines = headerBlock.split(/\r?\n/);
378
- var _iterator4 = _createForOfIteratorHelper(headerLines),
379
- _step4;
380
- try {
381
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
382
- var line = _step4.value;
383
- var colonIndex = line.indexOf(": ");
384
- if (colonIndex > 0) {
385
- var name = line.substring(0, colonIndex).toLowerCase();
386
- var value = line.substring(colonIndex + 2);
387
- headers[name] = value;
398
+
399
+ // Parse headers more carefully to handle binary data
400
+ var currentPos = 0;
401
+ while (currentPos < headerBlock.length) {
402
+ // Find next line ending (but be careful with binary data)
403
+ var lineEnd = headerBlock.indexOf("\r\n", currentPos);
404
+ if (lineEnd === -1) lineEnd = headerBlock.indexOf("\n", currentPos);
405
+ if (lineEnd === -1) lineEnd = headerBlock.length;
406
+ var line = headerBlock.substring(currentPos, lineEnd);
407
+ var colonIndex = line.indexOf(": ");
408
+ if (colonIndex > 0) {
409
+ var name = line.substring(0, colonIndex).toLowerCase();
410
+ var value = line.substring(colonIndex + 2);
411
+
412
+ // Special handling for known binary fields or detected binary data
413
+ if (name === "owner" || name === "signature") {
414
+ // These fields contain binary data that may have embedded newlines
415
+ // We need to read until we find the next header or end of headers
416
+ var valueStart = currentPos + colonIndex + 2;
417
+
418
+ // Look ahead to find where this field really ends
419
+ // The next header will start with a valid header name followed by ": "
420
+ var searchPos = valueStart;
421
+ var valueEnd = headerBlock.length;
422
+
423
+ // Look for the next valid header pattern
424
+ while (searchPos < headerBlock.length) {
425
+ var nextNewline = headerBlock.indexOf("\n", searchPos);
426
+ if (nextNewline === -1) break;
427
+
428
+ // Check if what follows looks like a header
429
+ var nextLineStart = nextNewline + 1;
430
+ var nextColon = headerBlock.indexOf(":", nextLineStart);
431
+
432
+ // Valid header should have colon relatively close to line start
433
+ if (nextColon > nextLineStart && nextColon < nextLineStart + 50) {
434
+ // Check if the text before colon looks like a header name (ASCII text)
435
+ var possibleHeaderName = headerBlock.substring(nextLineStart, nextColon);
436
+ var looksLikeHeader = /^[a-zA-Z0-9-]+$/.test(possibleHeaderName);
437
+ if (looksLikeHeader) {
438
+ // Found the next header, value ends at the newline before it
439
+ valueEnd = nextNewline;
440
+ break;
441
+ }
442
+ }
443
+ searchPos = nextNewline + 1;
444
+ }
445
+
446
+ // Extract the full value, trimming any trailing whitespace
447
+ value = headerBlock.substring(valueStart, valueEnd);
448
+
449
+ // Remove trailing CR if present (since we found the LF)
450
+ if (value.endsWith("\r")) {
451
+ value = value.substring(0, value.length - 1);
452
+ }
453
+
454
+ // Convert to Buffer to preserve binary
455
+ headers[name] = Buffer.from(value, "binary");
456
+ currentPos = valueEnd + 1;
457
+ } else {
458
+ // Regular text field
459
+ if (isBinaryData(value)) {
460
+ headers[name] = Buffer.from(value, "binary");
461
+ } else {
462
+ headers[name] = value;
463
+ }
464
+ currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1);
388
465
  }
466
+ } else {
467
+ // No colon found, skip this line
468
+ currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1);
389
469
  }
390
- } catch (err) {
391
- _iterator4.e(err);
392
- } finally {
393
- _iterator4.f();
394
470
  }
395
471
  var disposition = headers["content-disposition"];
396
472
  if (!disposition) continue;
397
473
  var partName = void 0;
398
474
  if (disposition === "inline") {
475
+ // This is the inline part
399
476
  partName = "body";
400
477
  bodyKeysList.push("body");
478
+
479
+ // Extract all headers from inline part as top-level fields
480
+ var restHeaders = _objectSpread({}, headers);
481
+ delete restHeaders["content-disposition"];
482
+
483
+ // Add each header from the inline part to the top level of result
484
+ for (var _i8 = 0, _Object$entries8 = Object.entries(restHeaders); _i8 < _Object$entries8.length; _i8++) {
485
+ var _Object$entries8$_i = _slicedToArray(_Object$entries8[_i8], 2),
486
+ key = _Object$entries8$_i[0],
487
+ _value2 = _Object$entries8$_i[1];
488
+ result[key] = _value2;
489
+ }
490
+
491
+ // If there's body content in the inline part, add it as 'body'
492
+ if (partBody) {
493
+ result[partName] = partBody;
494
+ }
401
495
  } else {
496
+ // Handle named form-data parts
402
497
  var nameMatch = disposition.match(/name="([^"]+)"/);
403
498
  partName = nameMatch ? nameMatch[1] : null;
404
499
  if (partName) {
405
- // Add the top-level key for this part
406
500
  var topLevelKey = partName.split("/")[0];
407
501
  bodyKeysList.push(topLevelKey);
408
502
  }
409
- }
410
- if (!partName) continue;
411
- var restHeaders = _objectSpread({}, headers);
412
- delete restHeaders["content-disposition"];
413
- if (Object.keys(restHeaders).length === 0) {
414
- result[partName] = partBody;
415
- } else if (!partBody) {
416
- result[partName] = restHeaders;
417
- } else {
418
- result[partName] = _objectSpread(_objectSpread({}, restHeaders), {}, {
419
- body: partBody
420
- });
503
+ if (!partName) continue;
504
+ var _restHeaders = _objectSpread({}, headers);
505
+ delete _restHeaders["content-disposition"];
506
+ if (Object.keys(_restHeaders).length === 0) {
507
+ result[partName] = partBody;
508
+ } else if (!partBody) {
509
+ result[partName] = _restHeaders;
510
+ } else {
511
+ result[partName] = _objectSpread(_objectSpread({}, _restHeaders), {}, {
512
+ body: partBody
513
+ });
514
+ }
421
515
  }
422
516
  }
423
517
  } catch (err) {
@@ -426,7 +520,6 @@ function parseMultipart(contentType, body) {
426
520
  _iterator3.f();
427
521
  }
428
522
  if (bodyKeysList.length > 0) {
429
- // Format as structured field list, preserving order and duplicates
430
523
  result["body-keys"] = bodyKeysList.map(function (k) {
431
524
  return "\"".concat(k, "\"");
432
525
  }).join(", ");
@@ -492,10 +585,10 @@ function httpsig_from(http) {
492
585
 
493
586
  // Convert flat structure to nested using flat.js
494
587
  var flat = {};
495
- for (var _i8 = 0, _Object$entries8 = Object.entries(withBodyKeys); _i8 < _Object$entries8.length; _i8++) {
496
- var _Object$entries8$_i = _slicedToArray(_Object$entries8[_i8], 2),
497
- key = _Object$entries8$_i[0],
498
- value = _Object$entries8$_i[1];
588
+ for (var _i9 = 0, _Object$entries9 = Object.entries(withBodyKeys); _i9 < _Object$entries9.length; _i9++) {
589
+ var _Object$entries9$_i = _slicedToArray(_Object$entries9[_i9], 2),
590
+ key = _Object$entries9$_i[0],
591
+ value = _Object$entries9$_i[1];
499
592
  if (key.includes("/")) {
500
593
  flat[key] = value;
501
594
  }
@@ -503,14 +596,14 @@ function httpsig_from(http) {
503
596
  if (Object.keys(flat).length > 0) {
504
597
  // Use flat_from to convert flat structure to nested
505
598
  var nested = (0, _flat.flat_from)(flat);
506
- for (var _i9 = 0, _Object$entries9 = Object.entries(nested); _i9 < _Object$entries9.length; _i9++) {
507
- var _Object$entries9$_i = _slicedToArray(_Object$entries9[_i9], 2),
508
- _key2 = _Object$entries9$_i[0],
509
- _value2 = _Object$entries9$_i[1];
510
- withBodyKeys[_key2] = _value2;
599
+ for (var _i0 = 0, _Object$entries0 = Object.entries(nested); _i0 < _Object$entries0.length; _i0++) {
600
+ var _Object$entries0$_i = _slicedToArray(_Object$entries0[_i0], 2),
601
+ _key2 = _Object$entries0$_i[0],
602
+ _value3 = _Object$entries0$_i[1];
603
+ withBodyKeys[_key2] = _value3;
511
604
  }
512
- for (var _i0 = 0, _Object$keys = Object.keys(flat); _i0 < _Object$keys.length; _i0++) {
513
- var _key3 = _Object$keys[_i0];
605
+ for (var _i1 = 0, _Object$keys = Object.keys(flat); _i1 < _Object$keys.length; _i1++) {
606
+ var _key3 = _Object$keys[_i1];
514
607
  delete withBodyKeys[_key3];
515
608
  }
516
609
  }
@@ -529,8 +622,8 @@ function httpsig_from(http) {
529
622
  delete result["content-digest"];
530
623
 
531
624
  // Extract hashpaths if any
532
- for (var _i1 = 0, _Object$keys2 = Object.keys(result); _i1 < _Object$keys2.length; _i1++) {
533
- var _key4 = _Object$keys2[_i1];
625
+ for (var _i10 = 0, _Object$keys2 = Object.keys(result); _i10 < _Object$keys2.length; _i10++) {
626
+ var _key4 = _Object$keys2[_i10];
534
627
  if (_key4.startsWith("hashpath")) {
535
628
  delete result[_key4];
536
629
  }
@@ -570,10 +663,10 @@ function httpsig_to(tabm) {
570
663
  // For flat structures, just return with normalized keys
571
664
  // This matches Erlang which returns the map unchanged
572
665
  var result = _objectSpread({}, inlineFieldHdrs);
573
- for (var _i10 = 0, _Object$entries0 = Object.entries(stripped); _i10 < _Object$entries0.length; _i10++) {
574
- var _Object$entries0$_i = _slicedToArray(_Object$entries0[_i10], 2),
575
- key = _Object$entries0$_i[0],
576
- value = _Object$entries0$_i[1];
666
+ for (var _i11 = 0, _Object$entries1 = Object.entries(stripped); _i11 < _Object$entries1.length; _i11++) {
667
+ var _Object$entries1$_i = _slicedToArray(_Object$entries1[_i11], 2),
668
+ key = _Object$entries1$_i[0],
669
+ value = _Object$entries1$_i[1];
577
670
  // Convert Buffers to strings if they're UTF-8 text
578
671
  if (Buffer.isBuffer(value)) {
579
672
  try {
@@ -623,31 +716,31 @@ function httpsig_to(tabm) {
623
716
  var headers = _objectSpread({}, inlineFieldHdrs);
624
717
 
625
718
  // Process each field - ao-types at top level should go to headers
626
- for (var _i11 = 0, _Object$entries1 = Object.entries(stripped); _i11 < _Object$entries1.length; _i11++) {
627
- var _Object$entries1$_i = _slicedToArray(_Object$entries1[_i11], 2),
628
- _key5 = _Object$entries1$_i[0],
629
- _value3 = _Object$entries1$_i[1];
719
+ for (var _i12 = 0, _Object$entries10 = Object.entries(stripped); _i12 < _Object$entries10.length; _i12++) {
720
+ var _Object$entries10$_i = _slicedToArray(_Object$entries10[_i12], 2),
721
+ _key5 = _Object$entries10$_i[0],
722
+ _value4 = _Object$entries10$_i[1];
630
723
  if (_key5 === "ao-types") {
631
724
  // Top-level ao-types goes to headers only
632
725
  // Convert Buffer to string if needed
633
- if (Buffer.isBuffer(_value3)) {
634
- headers[_key5] = _value3.toString("utf8");
726
+ if (Buffer.isBuffer(_value4)) {
727
+ headers[_key5] = _value4.toString("utf8");
635
728
  } else {
636
- headers[_key5] = _value3;
729
+ headers[_key5] = _value4;
637
730
  }
638
731
  } else if (_key5 === "body" || _key5 === inlineKeyVal) {
639
- bodyMap[_key5 === inlineKeyVal ? inlineKeyVal : "body"] = _value3;
640
- } else if (_typeof(_value3) === "object" && _value3 !== null && !Array.isArray(_value3) && !Buffer.isBuffer(_value3)) {
641
- bodyMap[_key5] = _value3;
642
- } else if (typeof _value3 === "string" && _value3.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
643
- headers[normalizeKey(_key5)] = _value3;
644
- } else if (Buffer.isBuffer(_value3) && _value3.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
732
+ bodyMap[_key5 === inlineKeyVal ? inlineKeyVal : "body"] = _value4;
733
+ } else if (_typeof(_value4) === "object" && _value4 !== null && !Array.isArray(_value4) && !Buffer.isBuffer(_value4)) {
734
+ bodyMap[_key5] = _value4;
735
+ } else if (typeof _value4 === "string" && _value4.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
736
+ headers[normalizeKey(_key5)] = _value4;
737
+ } else if (Buffer.isBuffer(_value4) && _value4.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
645
738
  // Convert Buffers to strings for headers
646
- var _str = _value3.toString("utf8");
739
+ var _str = _value4.toString("utf8");
647
740
  headers[normalizeKey(_key5)] = _str;
648
741
  } else if (_key5 !== "ao-types") {
649
742
  // Only add to bodyMap if it's not ao-types
650
- bodyMap[_key5] = _value3;
743
+ bodyMap[_key5] = _value4;
651
744
  }
652
745
  }
653
746
 
@@ -671,22 +764,22 @@ function httpsig_to(tabm) {
671
764
  b = _ref8[0];
672
765
  return a.localeCompare(b);
673
766
  });
674
- var _iterator5 = _createForOfIteratorHelper(sortedEntries),
675
- _step5;
767
+ var _iterator4 = _createForOfIteratorHelper(sortedEntries),
768
+ _step4;
676
769
  try {
677
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
678
- var _step5$value = _slicedToArray(_step5.value, 2),
679
- _key6 = _step5$value[0],
680
- _value4 = _step5$value[1];
681
- if (_typeof(_value4) === "object" && _value4 !== null && Object.keys(_value4).length === 1 && "body" in _value4) {
682
- var encoded = encodeBodyPart("".concat(_key6, "/body"), _value4, "body");
770
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
771
+ var _step4$value = _slicedToArray(_step4.value, 2),
772
+ _key6 = _step4$value[0],
773
+ _value5 = _step4$value[1];
774
+ if (_typeof(_value5) === "object" && _value5 !== null && Object.keys(_value5).length === 1 && "body" in _value5) {
775
+ var encoded = encodeBodyPart("".concat(_key6, "/body"), _value5, "body");
683
776
  parts.push({
684
777
  name: "".concat(_key6, "/body"),
685
778
  body: encoded
686
779
  });
687
780
  bodyKeysList.push(_key6);
688
781
  } else {
689
- var _encoded = encodeBodyPart(_key6, _value4, inlineKeyVal);
782
+ var _encoded = encodeBodyPart(_key6, _value5, inlineKeyVal);
690
783
  parts.push({
691
784
  name: _key6,
692
785
  body: _encoded
@@ -695,9 +788,9 @@ function httpsig_to(tabm) {
695
788
  }
696
789
  }
697
790
  } catch (err) {
698
- _iterator5.e(err);
791
+ _iterator4.e(err);
699
792
  } finally {
700
- _iterator5.f();
793
+ _iterator4.f();
701
794
  }
702
795
  var boundary = boundaryFromParts(parts);
703
796
  var bodyParts = parts.map(function (p) {
@@ -713,4 +806,18 @@ function httpsig_to(tabm) {
713
806
  });
714
807
  return addContentDigest(_result2);
715
808
  }
809
+ }
810
+
811
+ /**
812
+ * Convert structured message to flat format
813
+ */
814
+ function structured_to(msg) {
815
+ return msg;
816
+ }
817
+
818
+ /**
819
+ * Convert flat format to structured message
820
+ */
821
+ function structured_from(msg) {
822
+ return msg;
716
823
  }
package/cjs/index.js CHANGED
@@ -105,6 +105,12 @@ Object.defineProperty(exports, "normalize", {
105
105
  return _erl_json.normalize;
106
106
  }
107
107
  });
108
+ Object.defineProperty(exports, "result", {
109
+ enumerable: true,
110
+ get: function get() {
111
+ return _sendUtils.result;
112
+ }
113
+ });
108
114
  Object.defineProperty(exports, "rsaid", {
109
115
  enumerable: true,
110
116
  get: function get() {
@@ -158,6 +164,7 @@ var _utils = require("./utils.js");
158
164
  var _signer = require("./signer.js");
159
165
  var _send = require("./send.js");
160
166
  var _commit = require("./commit.js");
167
+ var _sendUtils = require("./send-utils.js");
161
168
  var _signerUtils = require("./signer-utils.js");
162
169
  var _erl_json = require("./erl_json.js");
163
170
  var _erl_str = require("./erl_str.js");
@@ -3,12 +3,18 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.verifyContentDigest = exports.toBuffer = exports.hasValidSignature = exports.getSignatureNames = exports.from = exports.extractKeys = void 0;
6
+ exports.verifyContentDigest = exports.toBuffer = exports.result = exports.hasValidSignature = exports.getSignatureNames = exports.from = exports.extractKeys = void 0;
7
7
  var _ramda = require("ramda");
8
+ var _utils = require("./utils.js");
8
9
  var _signerUtils = require("./signer-utils.js");
10
+ var _httpsig = require("./httpsig.js");
11
+ var _structured = require("./structured.js");
9
12
  var _base64url = _interopRequireDefault(require("base64url"));
10
- var _utils = require("./utils.js");
11
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
14
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
15
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
16
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
17
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
12
18
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
13
19
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
20
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
@@ -913,11 +919,75 @@ var stringToBuffer = function stringToBuffer(str) {
913
919
  }
914
920
  return buffer;
915
921
  };
922
+ var toMsg = /*#__PURE__*/function () {
923
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(req) {
924
+ var _req$headers;
925
+ var msg, arrayBuffer;
926
+ return _regenerator().w(function (_context) {
927
+ while (1) switch (_context.n) {
928
+ case 0:
929
+ msg = {};
930
+ req === null || req === void 0 || (_req$headers = req.headers) === null || _req$headers === void 0 || _req$headers.forEach(function (v, k) {
931
+ msg[k] = v;
932
+ });
933
+ if (!req.body) {
934
+ _context.n = 2;
935
+ break;
936
+ }
937
+ _context.n = 1;
938
+ return req.arrayBuffer();
939
+ case 1:
940
+ arrayBuffer = _context.v;
941
+ msg.body = typeof Buffer !== "undefined" ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer);
942
+ case 2:
943
+ return _context.a(2, msg);
944
+ }
945
+ }, _callee);
946
+ }));
947
+ return function toMsg(_x) {
948
+ return _ref.apply(this, arguments);
949
+ };
950
+ }();
951
+ var result = exports.result = /*#__PURE__*/function () {
952
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(response) {
953
+ var _from$signer, _from$hashpath;
954
+ var headers, msg, out, body, http, _from;
955
+ return _regenerator().w(function (_context2) {
956
+ while (1) switch (_context2.n) {
957
+ case 0:
958
+ headers = {};
959
+ response.headers.forEach(function (v, k) {
960
+ return headers[k] = v;
961
+ });
962
+ _context2.n = 1;
963
+ return toMsg(response);
964
+ case 1:
965
+ msg = _context2.v;
966
+ out = (0, _structured.structured_to)((0, _httpsig.httpsig_from)(msg));
967
+ body = Buffer.from(msg.body).toString();
968
+ http = {
969
+ headers: headers,
970
+ body: body
971
+ };
972
+ _from = from(http);
973
+ return _context2.a(2, {
974
+ signer: (_from$signer = _from === null || _from === void 0 ? void 0 : _from.signer) !== null && _from$signer !== void 0 ? _from$signer : null,
975
+ hashpath: (_from$hashpath = _from === null || _from === void 0 ? void 0 : _from.hashpath) !== null && _from$hashpath !== void 0 ? _from$hashpath : null,
976
+ headers: headers,
977
+ status: response.status,
978
+ body: body,
979
+ out: out["ao-result"] ? _from === null || _from === void 0 ? void 0 : _from.out : out
980
+ });
981
+ }
982
+ }, _callee2);
983
+ }));
984
+ return function result(_x2) {
985
+ return _ref2.apply(this, arguments);
986
+ };
987
+ }();
916
988
  var from = exports.from = function from(http) {
917
989
  var input = http.headers["signature-input"] || http.headers["Signature-Input"];
918
- if (!input) {
919
- return null;
920
- }
990
+ if (!input) return null;
921
991
 
922
992
  // Decode signature inputs
923
993
  var inputs = (0, _signerUtils.decodeSigInput)(input);
@@ -968,18 +1038,18 @@ var from = exports.from = function from(http) {
968
1038
  }
969
1039
 
970
1040
  // Convert the extracted components to JSON format
971
- var result = _toJSON(extractedComponents);
1041
+ var _result2 = _toJSON(extractedComponents);
972
1042
 
973
1043
  // Handle ao-result if present and pointing to other fields
974
1044
  if (aoResult && aoResult !== "body") {
975
1045
  // Return the value of the key specified by ao-result
976
1046
  // If the key doesn't exist, return undefined (or could return null/empty string)
977
1047
  return _objectSpread({
978
- out: result[aoResult] !== undefined ? result[aoResult] : ""
1048
+ out: _result2[aoResult] !== undefined ? _result2[aoResult] : ""
979
1049
  }, ret);
980
1050
  }
981
1051
  return _objectSpread({
982
- out: result
1052
+ out: _result2
983
1053
  }, ret);
984
1054
  }
985
1055
  return {
package/cjs/send.js CHANGED
@@ -10,10 +10,10 @@ exports.toHttpSigner = void 0;
10
10
  var _base64url = _interopRequireDefault(require("base64url"));
11
11
  var _index = require("./http-message-signatures/index.js");
12
12
  var _structuredHeaders = require("structured-headers");
13
- var _httpsig = require("./httpsig2.js");
13
+ var _httpsig = require("./httpsig.js");
14
+ var _structured = require("./structured.js");
15
+ var _sendUtils = require("./send-utils.js");
14
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
15
- function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
16
- function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
17
17
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
18
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
19
19
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
@@ -29,34 +29,61 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
29
29
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
30
30
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
31
31
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
32
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
33
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
32
34
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
33
35
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
34
36
  var augmentHeaders = _index.httpbis.augmentHeaders,
35
37
  createSignatureBase = _index.httpbis.createSignatureBase,
36
38
  createSigningParameters = _index.httpbis.createSigningParameters,
37
39
  formatSignatureBase = _index.httpbis.formatSignatureBase;
38
- function send(_x) {
40
+ var toMsg = /*#__PURE__*/function () {
41
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(req) {
42
+ var _req$headers;
43
+ var msg, arrayBuffer;
44
+ return _regenerator().w(function (_context) {
45
+ while (1) switch (_context.n) {
46
+ case 0:
47
+ msg = {};
48
+ req === null || req === void 0 || (_req$headers = req.headers) === null || _req$headers === void 0 || _req$headers.forEach(function (v, k) {
49
+ msg[k] = v;
50
+ });
51
+ if (!req.body) {
52
+ _context.n = 2;
53
+ break;
54
+ }
55
+ _context.n = 1;
56
+ return req.arrayBuffer();
57
+ case 1:
58
+ arrayBuffer = _context.v;
59
+ msg.body = typeof Buffer !== "undefined" ? Buffer.from(arrayBuffer) // Node.js
60
+ : new Uint8Array(arrayBuffer); // Browser
61
+ case 2:
62
+ return _context.a(2, msg);
63
+ }
64
+ }, _callee);
65
+ }));
66
+ return function toMsg(_x) {
67
+ return _ref.apply(this, arguments);
68
+ };
69
+ }();
70
+ function send(_x2) {
39
71
  return _send.apply(this, arguments);
40
72
  }
41
73
  function _send() {
42
- _send = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(signedMsg) {
74
+ _send = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(signedMsg) {
43
75
  var fetchImpl,
44
76
  fetchOptions,
45
77
  response,
46
- headers,
47
- http,
48
- _args2 = arguments,
78
+ _args3 = arguments,
49
79
  _t,
50
80
  _t2,
51
81
  _t3,
52
- _t4,
53
- _t5,
54
- _t6,
55
- _t7;
56
- return _regenerator().w(function (_context2) {
57
- while (1) switch (_context2.n) {
82
+ _t4;
83
+ return _regenerator().w(function (_context3) {
84
+ while (1) switch (_context3.n) {
58
85
  case 0:
59
- fetchImpl = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : fetch;
86
+ fetchImpl = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : fetch;
60
87
  fetchOptions = {
61
88
  method: signedMsg.method,
62
89
  headers: signedMsg.headers,
@@ -65,43 +92,29 @@ function _send() {
65
92
  if (signedMsg.body !== undefined && signedMsg.method !== "GET" && signedMsg.method !== "HEAD") {
66
93
  fetchOptions.body = signedMsg.body;
67
94
  }
68
- _context2.n = 1;
95
+ _context3.n = 1;
69
96
  return fetchImpl(signedMsg.url, fetchOptions);
70
97
  case 1:
71
- response = _context2.v;
98
+ response = _context3.v;
72
99
  if (!(response.status >= 400)) {
73
- _context2.n = 3;
100
+ _context3.n = 3;
74
101
  break;
75
102
  }
76
103
  _t = Error;
77
104
  _t2 = "".concat(response.status, ": ");
78
- _context2.n = 2;
105
+ _context3.n = 2;
79
106
  return response.text();
80
107
  case 2:
81
- _t3 = _context2.v;
108
+ _t3 = _context3.v;
82
109
  _t4 = _t2.concat.call(_t2, _t3);
83
110
  throw new _t(_t4);
84
111
  case 3:
85
- headers = {};
86
- if (response.headers && typeof response.headers.forEach === "function") {
87
- response.headers.forEach(function (v, k) {
88
- return headers[k] = v;
89
- });
90
- } else headers = response.headers;
91
- _t5 = headers;
92
- _context2.n = 4;
93
- return response.text();
112
+ _context3.n = 4;
113
+ return (0, _sendUtils.result)(response);
94
114
  case 4:
95
- _t6 = _context2.v;
96
- _t7 = response.status;
97
- http = {
98
- headers: _t5,
99
- body: _t6,
100
- status: _t7
101
- };
102
- return _context2.a(2, _objectSpread(_objectSpread({}, (0, _httpsig.from)(http)), http));
115
+ return _context3.a(2, _context3.v);
103
116
  }
104
- }, _callee2);
117
+ }, _callee3);
105
118
  }));
106
119
  return _send.apply(this, arguments);
107
120
  }
@@ -121,12 +134,12 @@ var toView = function toView(value) {
121
134
  var toHttpSigner = exports.toHttpSigner = function toHttpSigner(signer) {
122
135
  var params = ["alg", "keyid"].sort();
123
136
  return /*#__PURE__*/function () {
124
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(_ref) {
137
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(_ref2) {
125
138
  var request, fields, signatureBase, signatureInput, createCalled, create, result, signatureBuffer, signedHeaders, finalHeaders, _i, _Object$entries, _Object$entries$_i, key, value;
126
- return _regenerator().w(function (_context) {
127
- while (1) switch (_context.n) {
139
+ return _regenerator().w(function (_context2) {
140
+ while (1) switch (_context2.n) {
128
141
  case 0:
129
- request = _ref.request, fields = _ref.fields;
142
+ request = _ref2.request, fields = _ref2.fields;
130
143
  createCalled = false;
131
144
  create = function create(injected) {
132
145
  createCalled = true;
@@ -147,27 +160,27 @@ var toHttpSigner = exports.toHttpSigner = function toHttpSigner(signer) {
147
160
  var signatureBaseArray = createSignatureBase({
148
161
  fields: sortedFields
149
162
  }, request);
150
- signatureInput = (0, _structuredHeaders.serializeList)([[signatureBaseArray.map(function (_ref3) {
151
- var _ref4 = _slicedToArray(_ref3, 1),
152
- item = _ref4[0];
163
+ signatureInput = (0, _structuredHeaders.serializeList)([[signatureBaseArray.map(function (_ref4) {
164
+ var _ref5 = _slicedToArray(_ref4, 1),
165
+ item = _ref5[0];
153
166
  return (0, _structuredHeaders.parseItem)(item);
154
167
  }), signingParameters]]);
155
168
  signatureBaseArray.push(['"@signature-params"', [signatureInput]]);
156
169
  signatureBase = formatSignatureBase(signatureBaseArray);
157
170
  return new TextEncoder().encode(signatureBase);
158
171
  };
159
- _context.n = 1;
172
+ _context2.n = 1;
160
173
  return signer(create, "httpsig");
161
174
  case 1:
162
- result = _context.v;
175
+ result = _context2.v;
163
176
  if (createCalled) {
164
- _context.n = 2;
177
+ _context2.n = 2;
165
178
  break;
166
179
  }
167
180
  throw new Error("create() must be invoked in order to construct the data to sign");
168
181
  case 2:
169
182
  if (!(!result.signature || !result.address)) {
170
- _context.n = 3;
183
+ _context2.n = 3;
171
184
  break;
172
185
  }
173
186
  throw new Error("Signer must return signature and address");
@@ -181,14 +194,14 @@ var toHttpSigner = exports.toHttpSigner = function toHttpSigner(signer) {
181
194
  finalHeaders[key.toLowerCase()] = value;
182
195
  } else finalHeaders[key] = value;
183
196
  }
184
- return _context.a(2, _objectSpread(_objectSpread({}, request), {}, {
197
+ return _context2.a(2, _objectSpread(_objectSpread({}, request), {}, {
185
198
  headers: finalHeaders
186
199
  }));
187
200
  }
188
- }, _callee);
201
+ }, _callee2);
189
202
  }));
190
- return function (_x2) {
191
- return _ref2.apply(this, arguments);
203
+ return function (_x3) {
204
+ return _ref3.apply(this, arguments);
192
205
  };
193
206
  }();
194
207
  };
package/esm/httpsig.js CHANGED
@@ -286,7 +286,22 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
286
286
  return ""
287
287
  }
288
288
 
289
- // Parse multipart body
289
+ // Helper to detect if a string contains binary data
290
+ function isBinaryData(str) {
291
+ // Check first 100 chars for binary indicators
292
+ for (let i = 0; i < Math.min(str.length, 100); i++) {
293
+ const code = str.charCodeAt(i)
294
+ // Non-printable chars (except CR/LF/TAB)
295
+ if (code < 32 && code !== 9 && code !== 10 && code !== 13) return true
296
+ // High byte range that's not valid text
297
+ if (code > 126 && code < 160) return true
298
+ // Null byte is definitely binary
299
+ if (code === 0) return true
300
+ }
301
+ return false
302
+ }
303
+
304
+ // Parse multipart body - handles binary data in headers
290
305
  function parseMultipart(contentType, body) {
291
306
  const boundaryMatch = contentType.match(/boundary="?([^";\s]+)"?/)
292
307
  if (!boundaryMatch) return {}
@@ -295,8 +310,8 @@ function parseMultipart(contentType, body) {
295
310
  const boundaryDelim = `--${boundary}`
296
311
  const endBoundary = `--${boundary}--`
297
312
 
298
- // Remove the final boundary terminator if present
299
- let bodyContent = body
313
+ // Use binary encoding to preserve all bytes as character codes 0-255
314
+ let bodyContent = typeof body === "string" ? body : body.toString("binary")
300
315
  if (bodyContent.endsWith(endBoundary)) {
301
316
  bodyContent = bodyContent.substring(0, bodyContent.lastIndexOf(endBoundary))
302
317
  }
@@ -309,20 +324,98 @@ function parseMultipart(contentType, body) {
309
324
  const bodyKeysList = []
310
325
 
311
326
  for (const part of parts) {
312
- const [headerBlock, ...bodyParts] = part.split(DOUBLE_CRLF)
313
- let partBody = bodyParts.join(DOUBLE_CRLF)
314
-
315
- // Remove trailing CRLF
316
- partBody = partBody.replace(/\r?\n?$/, "")
327
+ // First split to find the headers/body boundary (double CRLF)
328
+ const headerBodySplit = part.indexOf(DOUBLE_CRLF)
329
+ let headerBlock, partBody
330
+
331
+ if (headerBodySplit !== -1) {
332
+ headerBlock = part.substring(0, headerBodySplit)
333
+ partBody = part.substring(headerBodySplit + DOUBLE_CRLF.length)
334
+ // Remove trailing CRLF from body
335
+ partBody = partBody.replace(/\r?\n?$/, "")
336
+ } else {
337
+ headerBlock = part
338
+ partBody = ""
339
+ }
317
340
 
318
341
  const headers = {}
319
- const headerLines = headerBlock.split(/\r?\n/)
320
- for (const line of headerLines) {
342
+
343
+ // Parse headers more carefully to handle binary data
344
+ let currentPos = 0
345
+ while (currentPos < headerBlock.length) {
346
+ // Find next line ending (but be careful with binary data)
347
+ let lineEnd = headerBlock.indexOf("\r\n", currentPos)
348
+ if (lineEnd === -1) lineEnd = headerBlock.indexOf("\n", currentPos)
349
+ if (lineEnd === -1) lineEnd = headerBlock.length
350
+
351
+ const line = headerBlock.substring(currentPos, lineEnd)
321
352
  const colonIndex = line.indexOf(": ")
353
+
322
354
  if (colonIndex > 0) {
323
355
  const name = line.substring(0, colonIndex).toLowerCase()
324
- const value = line.substring(colonIndex + 2)
325
- headers[name] = value
356
+ let value = line.substring(colonIndex + 2)
357
+
358
+ // Special handling for known binary fields or detected binary data
359
+ if (name === "owner" || name === "signature") {
360
+ // These fields contain binary data that may have embedded newlines
361
+ // We need to read until we find the next header or end of headers
362
+ let valueStart = currentPos + colonIndex + 2
363
+
364
+ // Look ahead to find where this field really ends
365
+ // The next header will start with a valid header name followed by ": "
366
+ let searchPos = valueStart
367
+ let valueEnd = headerBlock.length
368
+
369
+ // Look for the next valid header pattern
370
+ while (searchPos < headerBlock.length) {
371
+ let nextNewline = headerBlock.indexOf("\n", searchPos)
372
+ if (nextNewline === -1) break
373
+
374
+ // Check if what follows looks like a header
375
+ let nextLineStart = nextNewline + 1
376
+ let nextColon = headerBlock.indexOf(":", nextLineStart)
377
+
378
+ // Valid header should have colon relatively close to line start
379
+ if (nextColon > nextLineStart && nextColon < nextLineStart + 50) {
380
+ // Check if the text before colon looks like a header name (ASCII text)
381
+ let possibleHeaderName = headerBlock.substring(
382
+ nextLineStart,
383
+ nextColon
384
+ )
385
+ let looksLikeHeader = /^[a-zA-Z0-9-]+$/.test(possibleHeaderName)
386
+
387
+ if (looksLikeHeader) {
388
+ // Found the next header, value ends at the newline before it
389
+ valueEnd = nextNewline
390
+ break
391
+ }
392
+ }
393
+ searchPos = nextNewline + 1
394
+ }
395
+
396
+ // Extract the full value, trimming any trailing whitespace
397
+ value = headerBlock.substring(valueStart, valueEnd)
398
+
399
+ // Remove trailing CR if present (since we found the LF)
400
+ if (value.endsWith("\r")) {
401
+ value = value.substring(0, value.length - 1)
402
+ }
403
+
404
+ // Convert to Buffer to preserve binary
405
+ headers[name] = Buffer.from(value, "binary")
406
+ currentPos = valueEnd + 1
407
+ } else {
408
+ // Regular text field
409
+ if (isBinaryData(value)) {
410
+ headers[name] = Buffer.from(value, "binary")
411
+ } else {
412
+ headers[name] = value
413
+ }
414
+ currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1)
415
+ }
416
+ } else {
417
+ // No colon found, skip this line
418
+ currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1)
326
419
  }
327
420
  }
328
421
 
@@ -331,34 +424,48 @@ function parseMultipart(contentType, body) {
331
424
 
332
425
  let partName
333
426
  if (disposition === "inline") {
427
+ // This is the inline part
334
428
  partName = "body"
335
429
  bodyKeysList.push("body")
430
+
431
+ // Extract all headers from inline part as top-level fields
432
+ const restHeaders = { ...headers }
433
+ delete restHeaders["content-disposition"]
434
+
435
+ // Add each header from the inline part to the top level of result
436
+ for (const [key, value] of Object.entries(restHeaders)) {
437
+ result[key] = value
438
+ }
439
+
440
+ // If there's body content in the inline part, add it as 'body'
441
+ if (partBody) {
442
+ result[partName] = partBody
443
+ }
336
444
  } else {
445
+ // Handle named form-data parts
337
446
  const nameMatch = disposition.match(/name="([^"]+)"/)
338
447
  partName = nameMatch ? nameMatch[1] : null
339
448
  if (partName) {
340
- // Add the top-level key for this part
341
449
  const topLevelKey = partName.split("/")[0]
342
450
  bodyKeysList.push(topLevelKey)
343
451
  }
344
- }
345
452
 
346
- if (!partName) continue
453
+ if (!partName) continue
347
454
 
348
- const restHeaders = { ...headers }
349
- delete restHeaders["content-disposition"]
455
+ const restHeaders = { ...headers }
456
+ delete restHeaders["content-disposition"]
350
457
 
351
- if (Object.keys(restHeaders).length === 0) {
352
- result[partName] = partBody
353
- } else if (!partBody) {
354
- result[partName] = restHeaders
355
- } else {
356
- result[partName] = { ...restHeaders, body: partBody }
458
+ if (Object.keys(restHeaders).length === 0) {
459
+ result[partName] = partBody
460
+ } else if (!partBody) {
461
+ result[partName] = restHeaders
462
+ } else {
463
+ result[partName] = { ...restHeaders, body: partBody }
464
+ }
357
465
  }
358
466
  }
359
467
 
360
468
  if (bodyKeysList.length > 0) {
361
- // Format as structured field list, preserving order and duplicates
362
469
  result["body-keys"] = bodyKeysList.map(k => `"${k}"`).join(", ")
363
470
  }
364
471
 
@@ -656,3 +763,17 @@ export function httpsig_to(tabm) {
656
763
  return addContentDigest(result)
657
764
  }
658
765
  }
766
+
767
+ /**
768
+ * Convert structured message to flat format
769
+ */
770
+ export function structured_to(msg) {
771
+ return msg
772
+ }
773
+
774
+ /**
775
+ * Convert flat format to structured message
776
+ */
777
+ export function structured_from(msg) {
778
+ return msg
779
+ }
package/esm/index.js CHANGED
@@ -3,6 +3,7 @@ export { toAddr } from "./utils.js"
3
3
  export { sign, signer, createSigner } from "./signer.js"
4
4
  export { send } from "./send.js"
5
5
  export { commit } from "./commit.js"
6
+ export { result } from "./send-utils.js"
6
7
  export { extractPubKey, decodeSigInput, verify } from "./signer-utils.js"
7
8
  export { normalize, erl_json_to, erl_json_from } from "./erl_json.js"
8
9
  export { erl_str_from, erl_str_to } from "./erl_str.js"
@@ -1,7 +1,10 @@
1
1
  import { trim } from "ramda"
2
+ import { toAddr } from "./utils.js"
2
3
  import { decodeSigInput } from "./signer-utils.js"
4
+ import { httpsig_from } from "./httpsig.js"
5
+ import { structured_to } from "./structured.js"
3
6
  import base64url from "base64url"
4
- import { toAddr } from "./utils.js"
7
+
5
8
  /**
6
9
  * Get multipart boundary from content-type header
7
10
  */
@@ -856,12 +859,43 @@ const stringToBuffer = str => {
856
859
  return buffer
857
860
  }
858
861
 
862
+ const toMsg = async req => {
863
+ let msg = {}
864
+ req?.headers?.forEach((v, k) => {
865
+ msg[k] = v
866
+ })
867
+ if (req.body) {
868
+ const arrayBuffer = await req.arrayBuffer()
869
+ msg.body =
870
+ typeof Buffer !== "undefined"
871
+ ? Buffer.from(arrayBuffer)
872
+ : new Uint8Array(arrayBuffer)
873
+ }
874
+ return msg
875
+ }
876
+
877
+ export const result = async response => {
878
+ let headers = {}
879
+ response.headers.forEach((v, k) => (headers[k] = v))
880
+ const msg = await toMsg(response)
881
+ const out = structured_to(httpsig_from(msg))
882
+ const body = Buffer.from(msg.body).toString()
883
+ const http = { headers, body }
884
+ const _from = from(http)
885
+ return {
886
+ signer: _from?.signer ?? null,
887
+ hashpath: _from?.hashpath ?? null,
888
+ headers,
889
+ status: response.status,
890
+ body,
891
+ out: out["ao-result"] ? _from?.out : out,
892
+ }
893
+ }
894
+
859
895
  export const from = http => {
860
896
  const input =
861
897
  http.headers["signature-input"] || http.headers["Signature-Input"]
862
- if (!input) {
863
- return null
864
- }
898
+ if (!input) return null
865
899
 
866
900
  // Decode signature inputs
867
901
  const inputs = decodeSigInput(input)
package/esm/send.js CHANGED
@@ -1,13 +1,32 @@
1
1
  import base64url from "base64url"
2
2
  import { httpbis } from "./http-message-signatures/index.js"
3
3
  import { parseItem, serializeList } from "structured-headers"
4
+ import { httpsig_from } from "./httpsig.js"
5
+ import { structured_to } from "./structured.js"
6
+ import { result } from "./send-utils.js"
7
+
4
8
  const {
5
9
  augmentHeaders,
6
10
  createSignatureBase,
7
11
  createSigningParameters,
8
12
  formatSignatureBase,
9
13
  } = httpbis
10
- import { from } from "./httpsig2.js"
14
+
15
+ const toMsg = async req => {
16
+ let msg = {}
17
+ req?.headers?.forEach((v, k) => {
18
+ msg[k] = v
19
+ })
20
+ if (req.body) {
21
+ const arrayBuffer = await req.arrayBuffer()
22
+ msg.body =
23
+ typeof Buffer !== "undefined"
24
+ ? Buffer.from(arrayBuffer) // Node.js
25
+ : new Uint8Array(arrayBuffer) // Browser
26
+ }
27
+
28
+ return msg
29
+ }
11
30
 
12
31
  export async function send(signedMsg, fetchImpl = fetch) {
13
32
  const fetchOptions = {
@@ -27,13 +46,7 @@ export async function send(signedMsg, fetchImpl = fetch) {
27
46
  if (response.status >= 400) {
28
47
  throw new Error(`${response.status}: ${await response.text()}`)
29
48
  }
30
-
31
- let headers = {}
32
- if (response.headers && typeof response.headers.forEach === "function") {
33
- response.headers.forEach((v, k) => (headers[k] = v))
34
- } else headers = response.headers
35
- const http = { headers, body: await response.text(), status: response.status }
36
- return { ...from(http), ...http }
49
+ return await result(response)
37
50
  }
38
51
 
39
52
  export const httpSigName = address => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hbsig",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "main": "cjs/index.js",
5
5
  "license": "MIT",
6
6
  "devDependencies": {
@@ -14,6 +14,7 @@
14
14
  "@permaweb/aoconnect": "^0.0.85",
15
15
  "base64url": "^3.0.1",
16
16
  "fast-sha256": "^1.3.0",
17
+ "hbsig": "^0.1.5",
17
18
  "ramda": "^0.31.3",
18
19
  "structured-headers": "1.0.1"
19
20
  },