hbsig 0.2.0 → 0.2.2

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
@@ -244,20 +244,25 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
244
244
  value = _Object$entries6$_i[1];
245
245
  if (key === "body") continue;
246
246
  if (key === "ao-types") {
247
+ // Keep ao-types as-is (Buffer or string)
248
+ var valueStr = value;
249
+ if (Buffer.isBuffer(value)) {
250
+ valueStr = value.toString("binary");
251
+ }
247
252
  allEntries.push({
248
253
  key: "ao-types",
249
- line: "ao-types: ".concat(value)
254
+ line: "ao-types: ".concat(valueStr)
250
255
  });
251
256
  } else {
252
257
  // Handle Buffer values properly
253
- var valueStr = value;
258
+ var _valueStr = value;
254
259
  if (Buffer.isBuffer(value)) {
255
260
  // Use binary/latin1 encoding to preserve all byte values 0-255
256
- valueStr = value.toString("binary");
261
+ _valueStr = value.toString("binary");
257
262
  }
258
263
  allEntries.push({
259
264
  key: key,
260
- line: "".concat(key, ": ").concat(valueStr)
265
+ line: "".concat(key, ": ").concat(_valueStr)
261
266
  });
262
267
  }
263
268
  }
@@ -294,14 +299,14 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
294
299
  _value = _Object$entries7$_i[1];
295
300
  if (_key === "body") continue;
296
301
  // Handle Buffer values properly
297
- var _valueStr = _value;
302
+ var _valueStr2 = _value;
298
303
  if (Buffer.isBuffer(_value)) {
299
304
  // Use binary/latin1 encoding to preserve all byte values 0-255
300
- _valueStr = _value.toString("binary");
305
+ _valueStr2 = _value.toString("binary");
301
306
  }
302
307
  _allEntries.push({
303
308
  key: _key,
304
- line: "".concat(_key, ": ").concat(_valueStr)
309
+ line: "".concat(_key, ": ").concat(_valueStr2)
305
310
  });
306
311
  }
307
312
  var _lines = [];
@@ -343,17 +348,17 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
343
348
  return "";
344
349
  }
345
350
 
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
+ // Helper to detect if a Buffer contains binary data
352
+ function isBinaryData(buf) {
353
+ // Check first 100 bytes for binary indicators
354
+ for (var i = 0; i < Math.min(buf.length, 100); i++) {
355
+ var _byte = buf[i];
351
356
  // Non-printable chars (except CR/LF/TAB)
352
- if (code < 32 && code !== 9 && code !== 10 && code !== 13) return true;
357
+ if (_byte < 32 && _byte !== 9 && _byte !== 10 && _byte !== 13) return true;
353
358
  // High byte range that's not valid text
354
- if (code > 126 && code < 160) return true;
359
+ if (_byte > 126 && _byte < 160) return true;
355
360
  // Null byte is definitely binary
356
- if (code === 0) return true;
361
+ if (_byte === 0) return true;
357
362
  }
358
363
  return false;
359
364
  }
@@ -409,14 +414,12 @@ function parseMultipart(contentType, body) {
409
414
  var name = line.substring(0, colonIndex).toLowerCase();
410
415
  var value = line.substring(colonIndex + 2);
411
416
 
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
417
+ // Check if this might be binary data by looking at the first part
418
+ var valueBuf = Buffer.from(value, "binary");
419
+ var mightBeBinary = isBinaryData(valueBuf);
420
+ if (mightBeBinary) {
421
+ // Binary data may contain embedded newlines, so read until next header
416
422
  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
423
  var searchPos = valueStart;
421
424
  var valueEnd = headerBlock.length;
422
425
 
@@ -424,43 +427,27 @@ function parseMultipart(contentType, body) {
424
427
  while (searchPos < headerBlock.length) {
425
428
  var nextNewline = headerBlock.indexOf("\n", searchPos);
426
429
  if (nextNewline === -1) break;
427
-
428
- // Check if what follows looks like a header
429
430
  var nextLineStart = nextNewline + 1;
430
431
  var nextColon = headerBlock.indexOf(":", nextLineStart);
431
-
432
- // Valid header should have colon relatively close to line start
433
432
  if (nextColon > nextLineStart && nextColon < nextLineStart + 50) {
434
- // Check if the text before colon looks like a header name (ASCII text)
435
433
  var possibleHeaderName = headerBlock.substring(nextLineStart, nextColon);
436
434
  var looksLikeHeader = /^[a-zA-Z0-9-]+$/.test(possibleHeaderName);
437
435
  if (looksLikeHeader) {
438
- // Found the next header, value ends at the newline before it
439
436
  valueEnd = nextNewline;
440
437
  break;
441
438
  }
442
439
  }
443
440
  searchPos = nextNewline + 1;
444
441
  }
445
-
446
- // Extract the full value, trimming any trailing whitespace
447
442
  value = headerBlock.substring(valueStart, valueEnd);
448
-
449
- // Remove trailing CR if present (since we found the LF)
450
443
  if (value.endsWith("\r")) {
451
444
  value = value.substring(0, value.length - 1);
452
445
  }
453
-
454
- // Convert to Buffer to preserve binary
455
446
  headers[name] = Buffer.from(value, "binary");
456
447
  currentPos = valueEnd + 1;
457
448
  } else {
458
449
  // Regular text field
459
- if (isBinaryData(value)) {
460
- headers[name] = Buffer.from(value, "binary");
461
- } else {
462
- headers[name] = value;
463
- }
450
+ headers[name] = value;
464
451
  currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1);
465
452
  }
466
453
  } else {
@@ -490,7 +477,8 @@ function parseMultipart(contentType, body) {
490
477
 
491
478
  // If there's body content in the inline part, add it as 'body'
492
479
  if (partBody) {
493
- result[partName] = partBody;
480
+ // Convert back to Buffer to preserve binary data
481
+ result[partName] = Buffer.from(partBody, "binary");
494
482
  }
495
483
  } else {
496
484
  // Handle named form-data parts
@@ -504,12 +492,14 @@ function parseMultipart(contentType, body) {
504
492
  var _restHeaders = _objectSpread({}, headers);
505
493
  delete _restHeaders["content-disposition"];
506
494
  if (Object.keys(_restHeaders).length === 0) {
507
- result[partName] = partBody;
495
+ // Convert body back to Buffer
496
+ result[partName] = Buffer.from(partBody, "binary");
508
497
  } else if (!partBody) {
509
498
  result[partName] = _restHeaders;
510
499
  } else {
500
+ // Convert body back to Buffer
511
501
  result[partName] = _objectSpread(_objectSpread({}, _restHeaders), {}, {
512
- body: partBody
502
+ body: Buffer.from(partBody, "binary")
513
503
  });
514
504
  }
515
505
  }
@@ -667,35 +657,8 @@ function httpsig_to(tabm) {
667
657
  var _Object$entries1$_i = _slicedToArray(_Object$entries1[_i11], 2),
668
658
  key = _Object$entries1$_i[0],
669
659
  value = _Object$entries1$_i[1];
670
- // Convert Buffers to strings if they're UTF-8 text
671
- if (Buffer.isBuffer(value)) {
672
- try {
673
- var str = value.toString("utf8");
674
- // Check if it's valid UTF-8 that can be safely converted
675
- if (Buffer.from(str, "utf8").equals(value)) {
676
- // Check if all characters are printable
677
- var isPrintable = true;
678
- for (var i = 0; i < str.length; i++) {
679
- var code = str.charCodeAt(i);
680
- if (!(code >= 32 && code <= 126) && code !== 9 && code !== 10 && code !== 13) {
681
- isPrintable = false;
682
- break;
683
- }
684
- }
685
- if (isPrintable) {
686
- result[key] = str;
687
- } else {
688
- result[key] = value;
689
- }
690
- } else {
691
- result[key] = value;
692
- }
693
- } catch (e) {
694
- result[key] = value;
695
- }
696
- } else {
697
- result[key] = value;
698
- }
660
+ // Keep Buffers as Buffers - don't convert to strings
661
+ result[key] = value;
699
662
  }
700
663
 
701
664
  // Handle inline body key - move data from inline key to body
@@ -722,12 +685,8 @@ function httpsig_to(tabm) {
722
685
  _value4 = _Object$entries10$_i[1];
723
686
  if (_key5 === "ao-types") {
724
687
  // Top-level ao-types goes to headers only
725
- // Convert Buffer to string if needed
726
- if (Buffer.isBuffer(_value4)) {
727
- headers[_key5] = _value4.toString("utf8");
728
- } else {
729
- headers[_key5] = _value4;
730
- }
688
+ // Keep as Buffer if it's a Buffer, otherwise use as-is
689
+ headers[_key5] = _value4;
731
690
  } else if (_key5 === "body" || _key5 === inlineKeyVal) {
732
691
  bodyMap[_key5 === inlineKeyVal ? inlineKeyVal : "body"] = _value4;
733
692
  } else if (_typeof(_value4) === "object" && _value4 !== null && !Array.isArray(_value4) && !Buffer.isBuffer(_value4)) {
@@ -735,9 +694,8 @@ function httpsig_to(tabm) {
735
694
  } else if (typeof _value4 === "string" && _value4.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
736
695
  headers[normalizeKey(_key5)] = _value4;
737
696
  } else if (Buffer.isBuffer(_value4) && _value4.length <= MAX_HEADER_LENGTH && _key5 !== "ao-types") {
738
- // Convert Buffers to strings for headers
739
- var _str = _value4.toString("utf8");
740
- headers[normalizeKey(_key5)] = _str;
697
+ // Keep buffers as buffers for headers
698
+ headers[normalizeKey(_key5)] = _value4;
741
699
  } else if (_key5 !== "ao-types") {
742
700
  // Only add to bodyMap if it's not ao-types
743
701
  bodyMap[_key5] = _value4;
package/esm/httpsig.js CHANGED
@@ -204,7 +204,12 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
204
204
  if (key === "body") continue
205
205
 
206
206
  if (key === "ao-types") {
207
- allEntries.push({ key: "ao-types", line: `ao-types: ${value}` })
207
+ // Keep ao-types as-is (Buffer or string)
208
+ let valueStr = value
209
+ if (Buffer.isBuffer(value)) {
210
+ valueStr = value.toString("binary")
211
+ }
212
+ allEntries.push({ key: "ao-types", line: `ao-types: ${valueStr}` })
208
213
  } else {
209
214
  // Handle Buffer values properly
210
215
  let valueStr = value
@@ -286,17 +291,17 @@ function encodeBodyPart(partName, bodyPart, inlineKey) {
286
291
  return ""
287
292
  }
288
293
 
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
+ // Helper to detect if a Buffer contains binary data
295
+ function isBinaryData(buf) {
296
+ // Check first 100 bytes for binary indicators
297
+ for (let i = 0; i < Math.min(buf.length, 100); i++) {
298
+ const byte = buf[i]
294
299
  // Non-printable chars (except CR/LF/TAB)
295
- if (code < 32 && code !== 9 && code !== 10 && code !== 13) return true
300
+ if (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) return true
296
301
  // High byte range that's not valid text
297
- if (code > 126 && code < 160) return true
302
+ if (byte > 126 && byte < 160) return true
298
303
  // Null byte is definitely binary
299
- if (code === 0) return true
304
+ if (byte === 0) return true
300
305
  }
301
306
  return false
302
307
  }
@@ -355,14 +360,13 @@ function parseMultipart(contentType, body) {
355
360
  const name = line.substring(0, colonIndex).toLowerCase()
356
361
  let value = line.substring(colonIndex + 2)
357
362
 
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
+ // Check if this might be binary data by looking at the first part
364
+ const valueBuf = Buffer.from(value, "binary")
365
+ const mightBeBinary = isBinaryData(valueBuf)
363
366
 
364
- // Look ahead to find where this field really ends
365
- // The next header will start with a valid header name followed by ": "
367
+ if (mightBeBinary) {
368
+ // Binary data may contain embedded newlines, so read until next header
369
+ let valueStart = currentPos + colonIndex + 2
366
370
  let searchPos = valueStart
367
371
  let valueEnd = headerBlock.length
368
372
 
@@ -371,13 +375,10 @@ function parseMultipart(contentType, body) {
371
375
  let nextNewline = headerBlock.indexOf("\n", searchPos)
372
376
  if (nextNewline === -1) break
373
377
 
374
- // Check if what follows looks like a header
375
378
  let nextLineStart = nextNewline + 1
376
379
  let nextColon = headerBlock.indexOf(":", nextLineStart)
377
380
 
378
- // Valid header should have colon relatively close to line start
379
381
  if (nextColon > nextLineStart && nextColon < nextLineStart + 50) {
380
- // Check if the text before colon looks like a header name (ASCII text)
381
382
  let possibleHeaderName = headerBlock.substring(
382
383
  nextLineStart,
383
384
  nextColon
@@ -385,7 +386,6 @@ function parseMultipart(contentType, body) {
385
386
  let looksLikeHeader = /^[a-zA-Z0-9-]+$/.test(possibleHeaderName)
386
387
 
387
388
  if (looksLikeHeader) {
388
- // Found the next header, value ends at the newline before it
389
389
  valueEnd = nextNewline
390
390
  break
391
391
  }
@@ -393,24 +393,16 @@ function parseMultipart(contentType, body) {
393
393
  searchPos = nextNewline + 1
394
394
  }
395
395
 
396
- // Extract the full value, trimming any trailing whitespace
397
396
  value = headerBlock.substring(valueStart, valueEnd)
398
-
399
- // Remove trailing CR if present (since we found the LF)
400
397
  if (value.endsWith("\r")) {
401
398
  value = value.substring(0, value.length - 1)
402
399
  }
403
400
 
404
- // Convert to Buffer to preserve binary
405
401
  headers[name] = Buffer.from(value, "binary")
406
402
  currentPos = valueEnd + 1
407
403
  } else {
408
404
  // Regular text field
409
- if (isBinaryData(value)) {
410
- headers[name] = Buffer.from(value, "binary")
411
- } else {
412
- headers[name] = value
413
- }
405
+ headers[name] = value
414
406
  currentPos = lineEnd + (headerBlock[lineEnd] === "\r" ? 2 : 1)
415
407
  }
416
408
  } else {
@@ -439,7 +431,8 @@ function parseMultipart(contentType, body) {
439
431
 
440
432
  // If there's body content in the inline part, add it as 'body'
441
433
  if (partBody) {
442
- result[partName] = partBody
434
+ // Convert back to Buffer to preserve binary data
435
+ result[partName] = Buffer.from(partBody, "binary")
443
436
  }
444
437
  } else {
445
438
  // Handle named form-data parts
@@ -456,11 +449,16 @@ function parseMultipart(contentType, body) {
456
449
  delete restHeaders["content-disposition"]
457
450
 
458
451
  if (Object.keys(restHeaders).length === 0) {
459
- result[partName] = partBody
452
+ // Convert body back to Buffer
453
+ result[partName] = Buffer.from(partBody, "binary")
460
454
  } else if (!partBody) {
461
455
  result[partName] = restHeaders
462
456
  } else {
463
- result[partName] = { ...restHeaders, body: partBody }
457
+ // Convert body back to Buffer
458
+ result[partName] = {
459
+ ...restHeaders,
460
+ body: Buffer.from(partBody, "binary"),
461
+ }
464
462
  }
465
463
  }
466
464
  }
@@ -611,40 +609,8 @@ export function httpsig_to(tabm) {
611
609
  const result = { ...inlineFieldHdrs }
612
610
 
613
611
  for (const [key, value] of Object.entries(stripped)) {
614
- // Convert Buffers to strings if they're UTF-8 text
615
- if (Buffer.isBuffer(value)) {
616
- try {
617
- const str = value.toString("utf8")
618
- // Check if it's valid UTF-8 that can be safely converted
619
- if (Buffer.from(str, "utf8").equals(value)) {
620
- // Check if all characters are printable
621
- let isPrintable = true
622
- for (let i = 0; i < str.length; i++) {
623
- const code = str.charCodeAt(i)
624
- if (
625
- !(code >= 32 && code <= 126) &&
626
- code !== 9 &&
627
- code !== 10 &&
628
- code !== 13
629
- ) {
630
- isPrintable = false
631
- break
632
- }
633
- }
634
- if (isPrintable) {
635
- result[key] = str
636
- } else {
637
- result[key] = value
638
- }
639
- } else {
640
- result[key] = value
641
- }
642
- } catch (e) {
643
- result[key] = value
644
- }
645
- } else {
646
- result[key] = value
647
- }
612
+ // Keep Buffers as Buffers - don't convert to strings
613
+ result[key] = value
648
614
  }
649
615
 
650
616
  // Handle inline body key - move data from inline key to body
@@ -669,12 +635,8 @@ export function httpsig_to(tabm) {
669
635
  for (const [key, value] of Object.entries(stripped)) {
670
636
  if (key === "ao-types") {
671
637
  // Top-level ao-types goes to headers only
672
- // Convert Buffer to string if needed
673
- if (Buffer.isBuffer(value)) {
674
- headers[key] = value.toString("utf8")
675
- } else {
676
- headers[key] = value
677
- }
638
+ // Keep as Buffer if it's a Buffer, otherwise use as-is
639
+ headers[key] = value
678
640
  } else if (key === "body" || key === inlineKeyVal) {
679
641
  bodyMap[key === inlineKeyVal ? inlineKeyVal : "body"] = value
680
642
  } else if (
@@ -695,9 +657,8 @@ export function httpsig_to(tabm) {
695
657
  value.length <= MAX_HEADER_LENGTH &&
696
658
  key !== "ao-types"
697
659
  ) {
698
- // Convert Buffers to strings for headers
699
- const str = value.toString("utf8")
700
- headers[normalizeKey(key)] = str
660
+ // Keep buffers as buffers for headers
661
+ headers[normalizeKey(key)] = value
701
662
  } else if (key !== "ao-types") {
702
663
  // Only add to bodyMap if it's not ao-types
703
664
  bodyMap[key] = value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hbsig",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "main": "cjs/index.js",
5
5
  "license": "MIT",
6
6
  "devDependencies": {