braid-http 1.3.11 → 1.3.13

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.
@@ -116,22 +116,11 @@ function braidify_http (http) {
116
116
  // ***************************
117
117
 
118
118
  var normal_fetch,
119
- AbortController,
120
- Headers,
121
119
  is_nodejs = typeof window === 'undefined'
122
120
 
123
121
  if (is_nodejs) {
124
122
  // Nodejs
125
-
126
- // Note that reconnect logic doesn't work in node-fetch, because it
127
- // doesn't call the .catch() handler when the stream fails.
128
- //
129
- // See https://github.com/node-fetch/node-fetch/issues/753
130
-
131
- normal_fetch = require('node-fetch')
132
- AbortController = require('abort-controller')
133
- Headers = normal_fetch.Headers
134
- var to_whatwg_stream = require('web-streams-node').toWebReadableStream
123
+ normal_fetch = fetch
135
124
  } else {
136
125
  // Web Browser
137
126
  normal_fetch = window.fetch
@@ -418,9 +407,6 @@ async function braid_fetch (url, params = {}) {
418
407
 
419
408
  // Parse a stream of versions from the incoming bytes
420
409
  async function handle_fetch_stream (stream, cb, on_bytes) {
421
- if (is_nodejs)
422
- stream = to_whatwg_stream(stream)
423
-
424
410
  // Set up a reader
425
411
  var reader = stream.getReader(),
426
412
  parser = subscription_parser(cb)
@@ -595,7 +581,8 @@ function parse_headers (input) {
595
581
  var headers_source = input.slice(start, end).map(x => String.fromCharCode(x)).join('')
596
582
 
597
583
  // Convert "HTTP 200 OK" to a :status: 200 header
598
- headers_source = headers_source.replace(/^HTTP\/?\d*\.?\d* (\d\d\d).*\r?\n/, ':status: $1\r\n')
584
+ headers_source = headers_source.replace(/^HTTP\/?\d*\.?\d* (\d\d\d).*\r?\n/,
585
+ ':status: $1\r\n')
599
586
 
600
587
  var headers_length = headers_source.length
601
588
 
@@ -728,18 +715,21 @@ function parse_body (state) {
728
715
 
729
716
  // Parse Range Patch format
730
717
  {
718
+ var to_text = (bytes) =>
719
+ new TextDecoder('utf-8').decode(new Uint8Array(bytes))
720
+
731
721
  if (!('content-length' in last_patch.headers))
732
722
  return {
733
723
  result: 'error',
734
724
  message: 'no content-length in patch',
735
- patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input))
725
+ patch: last_patch, input: to_text(state.input)
736
726
  }
737
727
 
738
728
  if (!('content-range' in last_patch.headers))
739
729
  return {
740
730
  result: 'error',
741
731
  message: 'no content-range in patch',
742
- patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input))
732
+ patch: last_patch, input: to_text(state.input)
743
733
  }
744
734
 
745
735
  var content_length = parseInt(last_patch.headers['content-length'])
@@ -755,7 +745,7 @@ function parse_body (state) {
755
745
  return {
756
746
  result: 'error',
757
747
  message: 'cannot parse content-range in patch',
758
- patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input))
748
+ patch: last_patch, input: to_text(state.input)
759
749
  }
760
750
 
761
751
  last_patch.unit = match.unit
@@ -25,11 +25,15 @@ var assert = require('assert')
25
25
  //
26
26
  // {"some": "json object"}
27
27
  //
28
- function write_patches(res, patches) {
28
+ function write_patches (res, patches) {
29
29
  // `patches` must be a patch object or an array of patch objects
30
30
  // - Object: {unit, range, content}
31
31
  // - Array: [{unit, range, content}, ...]
32
32
 
33
+ if (typeof patches !== 'object')
34
+ console.error('We got bad patches!', {patches})
35
+
36
+ assert(patches)
33
37
  assert(typeof patches === 'object') // An array is also an object
34
38
 
35
39
  // An array of one patch behaves like a single patch
@@ -46,19 +50,29 @@ function write_patches(res, patches) {
46
50
  assert(typeof patch.unit === 'string')
47
51
  assert(typeof patch.range === 'string')
48
52
 
49
- if (typeof patch.content === 'string')
50
- patch.content = new TextEncoder().encode(patch.content)
51
-
52
53
  if (i > 0)
53
54
  res.write('\r\n\r\n')
54
55
 
55
- let extra_headers = Object.fromEntries(Object.entries(patch).filter(([k, v]) => k != 'unit' && k != 'range' && k != 'content'))
56
+ // Use a slick object_destructuring line to extract the extra_headers
57
+ var {unit, range, content, ...extra_headers} = patch
58
+
59
+ // Binarize the patch content
60
+ var binary_content = (typeof patch.content === 'string'
61
+ ? new TextEncoder().encode(patch.content)
62
+ : patch.content)
63
+
64
+ // Write the basic headers
65
+ res.write('Content-Length: ' + get_binary_length(binary_content) + '\r\n'
66
+ + 'Content-Range: ' + patch.unit + ' ' + patch.range + '\r\n')
67
+
68
+ // Write the extra headers:
69
+ for (var header in extra_headers)
70
+ res.write(`${header}: ${extra_headers[header]}\r\n`)
71
+
72
+ res.write('\r\n')
56
73
 
57
- res.write(`Content-Length: ${get_binary_length(patch.content)}\r
58
- Content-Range: ${patch.unit} ${patch.range}\r
59
- ${Object.entries(extra_headers).map(([k, v]) => `${k}: ${v}\r\n`).join('')}\r
60
- `)
61
- write_binary(res, patch.content)
74
+ // Write the patch content
75
+ write_binary(res, binary_content)
62
76
  })
63
77
  }
64
78
 
@@ -345,29 +359,27 @@ async function send_update(res, data, url, peer) {
345
359
  write_binary(res, body)
346
360
  }
347
361
 
348
- // console.log('sending version', {url, peer, version, parents, patches, body,
349
- // subscription: res.isSubscription})
362
+ // console.log('Sending Update', {url, peer, data, subscription: res.isSubscription})
350
363
 
351
- // Validate that the body and patches are strings,
352
- // or in the case of body, it could be binary
364
+ // Validate the body and patches
365
+ assert(!(patch && patches),
366
+ 'sendUpdate: cannot have both `update.patch` and `update.patches` set')
367
+ if (patch)
368
+ patches = [patch]
369
+ assert(!(body && patches),
370
+ 'sendUpdate: cannot have both `update.body` and `update.patch(es)')
371
+ assert(!patches || Array.isArray(patches),
372
+ 'sendUpdate: `patches` provided is not array')
373
+
374
+ // Validate body format
353
375
  if (body !== undefined) {
354
376
  assert(typeof body === 'string' || get_binary_length(body) != null)
355
377
  if (body instanceof Blob) body = await body.arrayBuffer()
356
- } else {
357
- // Only one of patch or patches can be set
358
- assert(!(patch && patches))
359
- assert((patch || patches) !== undefined)
360
- assert((patch || patches) !== null)
361
-
362
- // Patches must be an array
363
- if (patches)
364
- assert(Array.isArray(patches))
365
-
366
- // But if using `patch`, then we set `patches` to just that object
367
- if (patch)
368
- patches = patch
378
+ }
369
379
 
370
- // Now `patches` will be an array of patches or a single patch object.
380
+ // Validate patches format
381
+ if (patches !== undefined) {
382
+ // Now `patches` will be an array of patches
371
383
  //
372
384
  // This distinction is used in write_patches() to determine whether
373
385
  // to inline a single patch in the update body vs. writing out a
@@ -377,16 +389,21 @@ async function send_update(res, data, url, peer) {
377
389
  assert('unit' in p)
378
390
  assert('range' in p)
379
391
  assert('content' in p)
380
- assert(typeof p.content === 'string' || get_binary_length(p.content) != null)
392
+ assert(typeof p.content === 'string'
393
+ || get_binary_length(p.content) != null)
381
394
  if (p.content instanceof Blob) p.content = await p.content.arrayBuffer()
382
395
  }
383
396
  }
384
397
 
385
- var body_exists = body || body === ''
386
- assert(body_exists || patches, 'Missing body or patches')
387
- assert(!(body_exists && patches), 'Cannot send both body and patches')
398
+ // To send a response without a body, we just send an empty body
399
+ if (!patches && !body)
400
+ body = ''
388
401
 
389
- if (res.isSubscription) res.write(`HTTP ${status} OK\r\n`)
402
+ var reason =
403
+ status === 200 ? 'OK'
404
+ : 404 ? 'Not Found'
405
+ : 'Unknown'
406
+ if (res.isSubscription) res.write(`HTTP ${status} ${reason}\r\n`)
390
407
 
391
408
  // Write the headers or virtual headers
392
409
  for (var [header, value] of Object.entries(data)) {
@@ -396,6 +413,10 @@ async function send_update(res, data, url, peer) {
396
413
  if (value === undefined)
397
414
  continue
398
415
 
416
+ // Status headers are set in the status line (above)
417
+ if (header === 'status')
418
+ continue
419
+
399
420
  // Version and Parents get output in the Structured Headers format,
400
421
  // so we convert `value` from array to comma-separated strings.
401
422
  if (header === 'version') {
@@ -414,10 +435,12 @@ async function send_update(res, data, url, peer) {
414
435
  }
415
436
 
416
437
  // Write the patches or body
417
- if (body_exists) {
418
- let x = typeof body === 'string' ? new TextEncoder().encode(body) : body
419
- set_header('Content-Length', get_binary_length(x))
420
- write_body(x)
438
+ if (body || body === '') {
439
+ let binary = typeof body === 'string' ? new TextEncoder().encode(body) : body,
440
+ length = get_binary_length(binary)
441
+ assert(length !== undefined && length !== 'undefined')
442
+ set_header('Content-Length', length)
443
+ write_body(binary)
421
444
  } else
422
445
  write_patches(res, patches)
423
446
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-http",
3
- "version": "1.3.11",
3
+ "version": "1.3.13",
4
4
  "description": "An implementation of Braid-HTTP for Node.js and Browsers",
5
5
  "scripts": {
6
6
  "test": "node test/server.js"