New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

braid-http

Package Overview
Dependencies
Maintainers
1
Versions
83
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

braid-http - npm Package Compare versions

Comparing version 0.0.2 to 0.1.1

74

braid-http-client.js

@@ -139,3 +139,3 @@ var peer = Math.random().toString(36).substr(2)

Headers = window.Headers
window.fetch = braid_fetch
// window.fetch = braid_fetch
}

@@ -166,12 +166,26 @@

if (params.patches) {
console.assert(Array.isArray(params.patches), 'Patches must be array')
console.assert(!params.body, 'Cannot send both patches and body')
console.assert(typeof params.patches === 'object', 'Patches must be object or array')
params.patches = params.patches || []
params.headers.set('patches', params.patches.length)
params.body = (params.patches).map(patch => {
var length = `content-length: ${patch.content.length}`
var range = `content-range: ${patch.unit} ${patch.range}`
return `${length}\r\n${range}\r\n\r\n${patch.content}\r\n`
}).join('\r\n')
// We accept a single patch as an array of one patch
if (!Array.isArray(params.patches))
params.patches = [params.patches]
// If just one patch, send it directly!
if (params.patches.length === 1) {
let patch = params.patches[0]
params.headers.set('Content-Range', `${patch.unit} ${patch.range}`)
params.headers.set('Content-Length', `${patch.content.length}`)
params.body = patch.content
}
// Multiple patches get sent within a Patches: N block
else {
params.headers.set('Patches', params.patches.length)
params.body = (params.patches).map(patch => {
var length = `content-length: ${patch.content.length}`
var range = `content-range: ${patch.unit} ${patch.range}`
return `${length}\r\n${range}\r\n\r\n${patch.content}\r\n`
}).join('\r\n')
}
}

@@ -487,8 +501,14 @@

// Content-range is of the form '<unit> <range>' e.g. 'json .index'
var content_range_regex = /(\S+) (.*)/
function parse_body (state) {
// Parse Body Snapshot
var content_length = parseInt(state.headers['content-length'])
if (content_length !== NaN) {
if (!isNaN(content_length)) {
// We've read a Content-Length, so we have a block to parse
if (content_length > state.input.length) {
// But we haven't received the whole block yet
state.result = 'waiting'

@@ -498,5 +518,31 @@ return state

// We have the whole block!
var consumed_length = content_length + 2
state.result = 'success'
state.body = state.input.substring(0, content_length)
// If we have a content-range, then this is a patch
if (state.headers['content-range']) {
var match = state.headers['content-range'].match(content_range_regex)
if (!match)
return {
result: 'error',
message: 'cannot parse content-range',
range: state.headers['content-range']
}
state.patches = [{
unit: match[1],
range: match[2],
content: state.input.substring(0, content_length),
// Question: Perhaps we should include headers here, like we do for
// the Patches: N headers below?
// headers: state.headers
}]
}
// Otherwise, this is a snapshot body
else
state.body = state.input.substring(0, content_length)
state.input = state.input.substring(consumed_length)

@@ -542,3 +588,3 @@ return state

// Todo: support arbitrary patches, not just range-patch
// Todo: support custom patches, not just range-patch

@@ -569,5 +615,3 @@ // Parse Range Patch format

// Content-range is of the form '<unit> <range>' e.g. 'json .index'
var match = last_patch.headers['content-range'].match(/(\S+) (.*)/)
var match = last_patch.headers['content-range'].match(content_range_regex)
if (!match)

@@ -574,0 +618,0 @@ return {

var assert = require('assert')
// Write an array of patches into the pseudoheader format.
// Return a string of patches in pseudoheader format.
//
// The `patches` argument can be:
// - Array of patches
// - A single patch
//
// Multiple patches are generated like:
//
// Patches: n
//
// content-length: 21
// content-range: json .range
//
// {"some": "json object"}
//
// content-length: x
// ...
//
// A single patch is generated like:
//
// content-length: 21
// content-range: json .range
//
// {"some": "json object"}
//
function generate_patches(res, patches) {
// `patches` must be an object or an array
assert(typeof patches === 'object')
// An array of one patch behaves like a single patch
if (!Array.isArray(patches))
var patches = [patches]
for (let patch of patches) {

@@ -11,20 +43,19 @@ assert(typeof patch.unit === 'string')

// This will return something like:
// Patches: n
//
// content-length: 21
// content-range: json .range
//
// {"some": "json object"}
//
// content-length: x
// ...
var result = `Patches: ${patches.length}\r\n`
for (let patch of patches)
result += `\r
content-length: ${patch.content.length}\r
content-range: ${patch.unit} ${patch.range}\r
// Build up the string as a result
var result = ''
// Add `Patches: N` header if we have multiple patches
if (patches.length > 1)
result += `Patches: ${patches.length}\r\n\r\n`
// Generate each patch
patches.forEach((patch, i) => {
if (i > 0)
result += '\r\n\r\n'
result += `Content-Length: ${patch.content.length}\r
Content-Range: ${patch.unit} ${patch.range}\r
\r
${patch.content}\r
`
${patch.content}`
})
return result

@@ -37,77 +68,114 @@ }

function parse_patches (req, cb) {
// Todo: make this work in the case where there is no Patches: header, but
// Content-Range is still set, nonetheless.
var num_patches = req.headers.patches
var num_patches = req.headers.patches,
stream = req
// Parse a single patch from the request body
if (num_patches === undefined) {
let patches = []
let buffer = ""
if (num_patches === 0)
return cb(patches)
// We only support range patches right now, so there must be a
// Content-Range header.
assert(req.headers['content-range'], 'No patches to parse: need `Patches: N` or `Content-Range:` header in ' + JSON.stringify(req.headers))
stream.on('data', function parse (chunk) {
// Merge the latest chunk into our buffer
buffer = (buffer + chunk)
// Parse the Content-Range header
var match = req.headers['content-range'].match(/(\S+) (.*)/)
if (!match) {
console.error('Cannot parse Content-Range in', JSON.stringify(headers))
process.exit(1)
}
var [unit, range] = match.slice(1)
// We might have an extra newline at the start. (mike: why?)
buffer = buffer.trimStart()
// The contents of the patch is in the request body
var buffer = ''
// Read the body one chunk at a time
req.on('data', chunk => buffer = buffer + chunk)
// Then return it
req.on('end', () => {
patches = [{unit, range, content: buffer}]
cb(patches)
})
}
while (patches.length < num_patches) {
// First parse the patch headers. It ends with a double-newline.
// Let's see where that is.
var headers_end = buffer.match(/(\r?\n)(\r?\n)/)
// Parse multiple patches within a Patches: N block
else {
num_patches = parseInt(num_patches)
let patches = []
let buffer = ""
// Give up if we don't have a set of headers yet.
if (!headers_end)
return
// We check to send send patches each time we parse one. But if there
// are zero to parse, we will never check to send them.
if (num_patches === 0)
return cb([])
// Now we know where things end
var first_newline = headers_end[1],
headers_length = headers_end.index + first_newline.length,
blank_line = headers_end[2]
req.on('data', function parse (chunk) {
// Now let's parse those headers.
var headers = require('parse-headers')(
buffer.substring(0, headers_length)
)
// Merge the latest chunk into our buffer
buffer = (buffer + chunk)
// We require `content-length` to declare the length of the patch.
if (!('content-length' in headers)) {
// Print a nice error if it's missing
console.error('No content-length in', JSON.stringify(headers))
process.exit(1)
}
while (patches.length < num_patches) {
// We might have extra newlines at the start, because patches
// can be separated by arbitrary numbers of newlines
buffer = buffer.trimStart()
var body_length = parseInt(headers['content-length'])
// First parse the patch headers. It ends with a double-newline.
// Let's see where that is.
var headers_end = buffer.match(/(\r?\n)(\r?\n)/)
// Give up if we don't have the full patch yet.
if (buffer.length < headers_length + blank_line.length + body_length)
return
// Give up if we don't have a set of headers yet.
if (!headers_end)
return
// XX Todo: support custom patch types beyond content-range.
// Now we know where things end
var first_newline = headers_end[1],
headers_length = headers_end.index + first_newline.length,
blank_line = headers_end[2]
// Content-range is of the form '<unit> <range>' e.g. 'json .index'
var [unit, range] = headers['content-range'].match(/(\S+) (.*)/).slice(1)
var patch_content =
buffer.substring(headers_length + blank_line.length,
headers_length + blank_line.length + body_length)
// Now let's parse those headers.
var headers = require('parse-headers')(
buffer.substring(0, headers_length)
)
// We've got our patch!
patches.push({unit, range, content: patch_content})
// We require `content-length` to declare the length of the patch.
if (!('content-length' in headers)) {
// Print a nice error if it's missing
console.error('No content-length in', JSON.stringify(headers),
'from', {buffer, headers_length})
process.exit(1)
}
buffer = buffer.substring(headers_length + blank_line.length + body_length)
}
var body_length = parseInt(headers['content-length'])
// We got all the patches! Pause the stream and tell the callback!
stream.pause()
cb(patches)
})
stream.on('end', () => {
// If the stream ends before we get everything, then return what we
// did receive
console.error('Stream ended!')
if (patches.length !== num_patches)
console.error(`Got an incomplete PUT: ${patches.length}/${num_patches} patches were received`)
})
// Give up if we don't have the full patch yet.
if (buffer.length < headers_length + blank_line.length + body_length)
return
// XX Todo: support custom patch types beyond content-range.
// Content-range is of the form '<unit> <range>' e.g. 'json .index'
var match = headers['content-range'].match(/(\S+) (.*)/)
if (!match) {
console.error('Cannot parse Content-Range in', JSON.stringify(headers))
process.exit(1)
}
var [unit, range] = match.slice(1)
var patch_content =
buffer.substring(headers_length + blank_line.length,
headers_length + blank_line.length + body_length)
// We've got our patch!
patches.push({unit, range, content: patch_content})
buffer = buffer.substring(headers_length + blank_line.length + body_length)
}
// We got all the patches! Pause the stream and tell the callback!
req.pause()
cb(patches)
})
req.on('end', () => {
// If the stream ends before we get everything, then return what we
// did receive
console.error('Request stream ended!')
if (patches.length !== num_patches)
console.error(`Got an incomplete PUT: ${patches.length}/${num_patches} patches were received`)
})
}
}

@@ -121,3 +189,2 @@

res.setHeader('Range-Request-Allow-Units', 'json')
res.setHeader("Patches", "OK")

@@ -169,2 +236,3 @@ // Extract braid info from headers

res.setHeader('cache-control', 'no-cache, no-transform')
res.setHeader('transfer-encoding', '')

@@ -205,3 +273,3 @@ var connected = true

if (res.isSubscription)
res.write('\r\n' + body + '\r\n')
res.write('\r\n' + body)
else

@@ -219,12 +287,22 @@ res.write(body)

assert(patches !== undefined)
patches.forEach(p => assert(typeof p.content === 'string'))
assert(patches !== null)
assert(typeof patches === 'object')
if (Array.isArray(patches))
patches.forEach(p => assert(typeof p.content === 'string'))
}
assert(body || patches, 'Missing body or patches')
assert(!(body && patches), 'Cannot send both body and patches')
// Write the headers or virtual headers
for (var [header, value] of Object.entries(data)) {
header = header.toLowerCase()
// Version and Parents get output in the Structured Headers format
if (header === 'version')
if (header === 'version') {
header = 'Version' // Capitalize for prettiness
value = JSON.stringify(value)
else if (header === 'parents')
} else if (header === 'parents') {
header = 'Parents' // Capitalize for prettiness
value = parents.map(JSON.stringify).join(", ")
}

@@ -239,11 +317,7 @@ // We don't output patches or body yet

// Write the patches or body
if (Array.isArray(patches))
res.write(generate_patches(res, patches)) // adds its own newline
else if (typeof body === 'string') {
set_header('content-length', body.length)
if (typeof body === 'string') {
set_header('Content-Length', body.length)
write_body(body)
} else {
console.trace("Missing body or patches")
process.exit()
}
} else
res.write(generate_patches(res, patches))

@@ -253,3 +327,3 @@ // Add a newline to prepare for the next version

if (res.isSubscription) {
var extra_newlines = 0
var extra_newlines = 1
if (res.is_firefox)

@@ -256,0 +330,0 @@ // Work around Firefox network buffering bug

{
"name": "braid-http",
"version": "0.0.2",
"version": "0.1.1",
"description": "An implementation of Braid-HTTP for Node.js and Browsers",

@@ -5,0 +5,0 @@ "scripts": {

# Braid-HTTP
This polyfill library implements the [Braid-HTTP v03 protocol](https://github.com/braid-org/braid-spec/blob/master/draft-toomim-httpbis-braid-http-03.txt) in Javascript. It extends the existing browser `fetch()` API, and the nodejs `http` library, with the ability to speak Braid.
This polyfill library implements the [Braid-HTTP v03 protocol](https://github.com/braid-org/braid-spec/blob/master/draft-toomim-httpbis-braid-http-03.txt) in Javascript. It gives browsers a `braid_fetch()` drop-in replacement for the `fetch()` API, and gives nodejs an `http` plugin, allowing them to speak Braid in a simple way.

@@ -14,2 +14,6 @@ Developed in [braid.org](https://braid.org).

<script src="https://unpkg.com/braid-http/braid-http-client.js"></script>
<script>
// To live on the cutting edge, you can now replace the browser's fetch() if desired:
// window.fetch = braid_fetch
</script>
```

@@ -102,3 +106,4 @@

try {
for await (var v of fetch('/chat', {subscribe: true}).subscription) {
var subscription_iterator = fetch('/chat', {subscribe: true}).subscription
for await (var v of subscription_iterator) {
// Updates might come in the form of patches:

@@ -105,0 +110,0 @@ if (v.patches)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc