braid-http 0.1.11 → 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/braid-http-client.js +16 -1
- package/braid-http-server.js +49 -21
- package/package.json +1 -1
package/braid-http-client.js
CHANGED
|
@@ -49,6 +49,7 @@ function braidify_http (http) {
|
|
|
49
49
|
options.headers.peer = options.headers.peer || peer
|
|
50
50
|
|
|
51
51
|
// Wrap the callback to provide our new .on('version', ...) feature
|
|
52
|
+
// on nodejs servers
|
|
52
53
|
var on_version,
|
|
53
54
|
on_error,
|
|
54
55
|
orig_cb = cb
|
|
@@ -362,12 +363,19 @@ var subscription_parser = (cb) => ({
|
|
|
362
363
|
|
|
363
364
|
// Maybe we parsed a version! That's cool!
|
|
364
365
|
if (this.state.result === 'success') {
|
|
366
|
+
let ignore_headers = {
|
|
367
|
+
version: true,
|
|
368
|
+
parents: true,
|
|
369
|
+
patches: true,
|
|
370
|
+
'content-length': true,
|
|
371
|
+
'content-range': true,
|
|
372
|
+
}
|
|
365
373
|
this.cb({
|
|
366
374
|
version: this.state.version,
|
|
367
375
|
parents: this.state.parents,
|
|
368
376
|
body: this.state.body,
|
|
369
377
|
patches: this.state.patches,
|
|
370
|
-
|
|
378
|
+
...((x => Object.keys(x).length ? {extra_headers: x} : {})(Object.fromEntries(Object.entries(this.state.headers).filter(([k, v]) => !ignore_headers[k]))))
|
|
371
379
|
})
|
|
372
380
|
|
|
373
381
|
// Reset the parser for the next version!
|
|
@@ -626,6 +634,13 @@ function parse_body (state) {
|
|
|
626
634
|
last_patch.range = match.range
|
|
627
635
|
last_patch.content = state.input.substr(0, content_length)
|
|
628
636
|
|
|
637
|
+
// instead of headers, we'll create an "extra_headers" field that ignore the headers we've used
|
|
638
|
+
last_patch.extra_headers = last_patch.headers
|
|
639
|
+
delete last_patch.headers
|
|
640
|
+
delete last_patch.extra_headers['content-length']
|
|
641
|
+
delete last_patch.extra_headers['content-range']
|
|
642
|
+
if (!Object.keys(last_patch.extra_headers).length) delete last_patch.extra_headers
|
|
643
|
+
|
|
629
644
|
// Consume the parsed input
|
|
630
645
|
state.input = state.input.substring(content_length)
|
|
631
646
|
}
|
package/braid-http-server.js
CHANGED
|
@@ -26,34 +26,37 @@ var assert = require('assert')
|
|
|
26
26
|
// {"some": "json object"}
|
|
27
27
|
//
|
|
28
28
|
function generate_patches(res, patches) {
|
|
29
|
+
var result = ''
|
|
30
|
+
|
|
31
|
+
// `patches` must be a patch object or an array of patch objects
|
|
32
|
+
// - Object: {unit, range, content}
|
|
33
|
+
// - Array: [{unit, range, content}, ...]
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
assert(typeof patches === 'object')
|
|
35
|
+
assert(typeof patches === 'object') // An array is also an object
|
|
32
36
|
|
|
33
37
|
// An array of one patch behaves like a single patch
|
|
34
|
-
if (
|
|
35
|
-
|
|
38
|
+
if (Array.isArray(patches)) {
|
|
39
|
+
|
|
40
|
+
// Add `Patches: N` header if array
|
|
41
|
+
result += `Patches: ${patches.length}\r\n\r\n`
|
|
42
|
+
} else
|
|
43
|
+
// Else, we'll out put a single patch
|
|
44
|
+
patches = [patches]
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
// Generate each patch
|
|
47
|
+
patches.forEach((patch, i) => {
|
|
38
48
|
assert(typeof patch.unit === 'string')
|
|
39
49
|
assert(typeof patch.range === 'string')
|
|
40
50
|
assert(typeof patch.content === 'string')
|
|
41
|
-
}
|
|
42
51
|
|
|
43
|
-
// Build up the string as a result
|
|
44
|
-
var result = ''
|
|
45
|
-
|
|
46
|
-
// Add `Patches: N` header
|
|
47
|
-
result += `Patches: ${patches.length}\r\n\r\n`
|
|
48
|
-
|
|
49
|
-
// Generate each patch
|
|
50
|
-
patches.forEach((patch, i) => {
|
|
51
52
|
if (i > 0)
|
|
52
53
|
result += '\r\n\r\n'
|
|
53
54
|
|
|
55
|
+
let extra_headers = Object.fromEntries(Object.entries(patch).filter(([k, v]) => k != 'unit' && k != 'range' && k != 'content'))
|
|
56
|
+
|
|
54
57
|
result += `Content-Length: ${patch.content.length}\r
|
|
55
58
|
Content-Range: ${patch.unit} ${patch.range}\r
|
|
56
|
-
\r
|
|
59
|
+
${Object.entries(extra_headers).map(([k, v]) => `${k}: ${v}\r\n`).join('')}\r
|
|
57
60
|
${patch.content}`
|
|
58
61
|
})
|
|
59
62
|
return result
|
|
@@ -237,7 +240,10 @@ function braidify (req, res, next) {
|
|
|
237
240
|
res.statusCode = 209
|
|
238
241
|
res.setHeader("subscribe", req.headers.subscribe)
|
|
239
242
|
res.setHeader('cache-control', 'no-cache, no-transform')
|
|
240
|
-
if (req.httpVersionMajor == 1)
|
|
243
|
+
if (req.httpVersionMajor == 1) {
|
|
244
|
+
// Explicitly disable transfer-encoding chunked for http 1
|
|
245
|
+
res.setHeader('transfer-encoding', '')
|
|
246
|
+
}
|
|
241
247
|
|
|
242
248
|
// Tell nginx not to buffer the subscription
|
|
243
249
|
res.setHeader('X-Accel-Buffering', 'no')
|
|
@@ -268,7 +274,7 @@ function braidify (req, res, next) {
|
|
|
268
274
|
}
|
|
269
275
|
|
|
270
276
|
function send_version(res, data, url, peer) {
|
|
271
|
-
var {version, parents, patches, body} = data
|
|
277
|
+
var {version, parents, patches, patch, body} = data
|
|
272
278
|
|
|
273
279
|
function set_header (key, val) {
|
|
274
280
|
if (res.isSubscription)
|
|
@@ -290,12 +296,34 @@ function send_version(res, data, url, peer) {
|
|
|
290
296
|
if (body !== undefined)
|
|
291
297
|
assert(typeof body === 'string')
|
|
292
298
|
else {
|
|
293
|
-
|
|
294
|
-
assert(
|
|
299
|
+
// Only one of patch or patches can be set
|
|
300
|
+
assert(!(patch && patches))
|
|
301
|
+
assert((patch || patches) !== undefined)
|
|
302
|
+
assert((patch || patches) !== null)
|
|
303
|
+
|
|
304
|
+
// Patches must be an array
|
|
305
|
+
if (patches)
|
|
306
|
+
assert(Array.isArray(patches))
|
|
307
|
+
|
|
308
|
+
// But if using `patch`, then we set `patches` to just that object
|
|
309
|
+
if (patch)
|
|
310
|
+
patches = patch
|
|
311
|
+
|
|
312
|
+
// Now `patches` will be an array of patches or a single patch object.
|
|
313
|
+
//
|
|
314
|
+
// This distinction is used in generate_patches() to determine whether
|
|
315
|
+
// to inline a single patch in the update body vs. writing out a
|
|
316
|
+
// Patches: N block.
|
|
295
317
|
assert(typeof patches === 'object')
|
|
296
318
|
if (Array.isArray(patches))
|
|
297
|
-
patches.forEach(p =>
|
|
319
|
+
patches.forEach(p => {
|
|
320
|
+
assert('unit' in p)
|
|
321
|
+
assert('range' in p)
|
|
322
|
+
assert('content' in p)
|
|
323
|
+
assert(typeof p.content === 'string')
|
|
324
|
+
})
|
|
298
325
|
}
|
|
326
|
+
|
|
299
327
|
var body_exists = body || body === ''
|
|
300
328
|
assert(body_exists || patches, 'Missing body or patches')
|
|
301
329
|
assert(!(body_exists && patches), 'Cannot send both body and patches')
|
|
@@ -314,7 +342,7 @@ function send_version(res, data, url, peer) {
|
|
|
314
342
|
}
|
|
315
343
|
|
|
316
344
|
// We don't output patches or body yet
|
|
317
|
-
else if (header === 'patches' || header
|
|
345
|
+
else if (header === 'patches' || header === 'body' || header === 'patch')
|
|
318
346
|
continue
|
|
319
347
|
|
|
320
348
|
set_header(header, value)
|