braid-http
Advanced tools
Comparing version 0.3.12 to 0.3.13
@@ -76,3 +76,3 @@ // var peer = Math.random().toString(36).substr(2) | ||
res.orig_on('data', (chunk) => { | ||
parser.read(chunk.toString()) | ||
parser.read(chunk) | ||
}) | ||
@@ -190,3 +190,3 @@ } | ||
params.headers.set('Content-Range', `${patch.unit} ${patch.range}`) | ||
params.headers.set('Content-Length', `${patch.content.length}`) | ||
params.headers.set('Content-Length', `${(new TextEncoder().encode(patch.content)).length}`) | ||
params.body = patch.content | ||
@@ -199,3 +199,3 @@ } | ||
params.body = (params.patches).map(patch => { | ||
var length = `content-length: ${patch.content.length}` | ||
var length = `content-length: ${(new TextEncoder().encode(patch.content)).length}` | ||
var range = `content-range: ${patch.unit} ${patch.range}` | ||
@@ -324,3 +324,2 @@ return `${length}\r\n${range}\r\n\r\n${patch.content}\r\n` | ||
var reader = stream.getReader(), | ||
decoder = new TextDecoder('utf-8'), | ||
parser = subscription_parser(cb) | ||
@@ -348,3 +347,3 @@ | ||
// Tell the parser to process some more stream | ||
parser.read(decoder.decode(value)) | ||
parser.read(value) | ||
} | ||
@@ -361,3 +360,3 @@ } | ||
// A parser keeps some parse state | ||
state: {input: ''}, | ||
state: {input: []}, | ||
@@ -372,6 +371,6 @@ // And reports back new versions as soon as they are ready | ||
// Store the new input! | ||
this.state.input += input | ||
this.state.input.push(...input) | ||
// Now loop through the input and parse until we hit a dead end | ||
while (this.state.input.trim() !== '') { | ||
while (this.state.input.length) { | ||
@@ -455,25 +454,10 @@ // Try to parse an update | ||
function swallow_blank_lines (input) { | ||
var blank_lines = /(\r\n|\n)*/.exec(input)[0] | ||
return input.substr(blank_lines.length) | ||
} | ||
// Parsing helpers | ||
function parse_headers (input) { | ||
input = swallow_blank_lines(input) | ||
// First, find the start & end block of the headers. The headers start | ||
// when there are no longer newlines, and end at the first double-newline. | ||
var h = extractHeader(input) | ||
if (!h) return {result: 'waiting'} | ||
// Look for the double-newline at the end of the headers | ||
var headers_end = input.match(/(\r?\n)\r?\n/) | ||
// ...if we found none, then we need to wait for more input to complete | ||
// the headers.. | ||
if (!headers_end) | ||
return {result: 'waiting'} | ||
// We now know where the headers are to parse! | ||
var headers_length = headers_end.index + headers_end[1].length, | ||
headers_source = input.substring(0, headers_length) | ||
var headers_source = h.header_string | ||
var headers_length = headers_source.length | ||
@@ -515,12 +499,4 @@ // Let's parse them! First define some variables: | ||
// Update the input | ||
input = input.substring(headers_length) | ||
input = h.remaining_bytes | ||
// Swallow the final blank line ending the headers | ||
if (input.substr(0, 2) === '\r\n') | ||
// Swallow \r\n | ||
input = input.substr(2) | ||
else | ||
// Swallow \n | ||
input = input.substr(1) | ||
// And return the parsed result | ||
@@ -550,3 +526,2 @@ return { result: 'success', headers, input } | ||
// We have the whole block! | ||
var consumed_length = content_length + 2 | ||
state.result = 'success' | ||
@@ -566,3 +541,3 @@ | ||
range: match.range, | ||
content: state.input.substring(0, content_length), | ||
content: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input.slice(0, content_length))), | ||
@@ -578,5 +553,5 @@ // Question: Perhaps we should include headers here, like we do for | ||
else | ||
state.body = state.input.substring(0, content_length) | ||
state.body = (new TextDecoder('utf-8')).decode(new Uint8Array(state.input.slice(0, content_length))) | ||
state.input = state.input.substring(consumed_length) | ||
state.input = state.input.slice(content_length) | ||
return state | ||
@@ -596,4 +571,2 @@ } | ||
state.input = state.input.trimStart() | ||
// Are we starting a new patch? | ||
@@ -630,3 +603,3 @@ if (!last_patch || 'content' in last_patch) { | ||
message: 'no content-length in patch', | ||
patch: last_patch, input: state.input | ||
patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input)) | ||
} | ||
@@ -638,3 +611,3 @@ | ||
message: 'no content-range in patch', | ||
patch: last_patch, input: state.input | ||
patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input)) | ||
} | ||
@@ -655,3 +628,3 @@ | ||
message: 'cannot parse content-range in patch', | ||
patch: last_patch, input: state.input | ||
patch: last_patch, input: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input)) | ||
} | ||
@@ -661,3 +634,3 @@ | ||
last_patch.range = match.range | ||
last_patch.content = state.input.substr(0, content_length) | ||
last_patch.content = (new TextDecoder('utf-8')).decode(new Uint8Array(state.input.slice(0, content_length))) | ||
last_patch.extra_headers = extra_headers(last_patch.headers) | ||
@@ -667,3 +640,3 @@ delete last_patch.headers // We only keep the extra headers ^^ | ||
// Consume the parsed input | ||
state.input = state.input.substring(content_length) | ||
state.input = state.input.slice(content_length) | ||
} | ||
@@ -705,2 +678,56 @@ } | ||
// a parsing utility function that will inspect a byte array of incoming data | ||
// to see if there is header information at the beginning, | ||
// namely some non-newline characters followed by two newlines | ||
function extractHeader(input) { | ||
// Find the start of the headers | ||
let begin_headers_i = 0; | ||
while (input[begin_headers_i] === 13 || input[begin_headers_i] === 10) { | ||
begin_headers_i++; | ||
} | ||
if (begin_headers_i === input.length) { | ||
return null; // Incomplete headers | ||
} | ||
// Look for the double-newline at the end of the headers | ||
let end_headers_i = begin_headers_i; | ||
let size_of_tail = 0; | ||
while (end_headers_i < input.length) { | ||
if (input[end_headers_i] === 10 && input[end_headers_i + 1] === 10) { | ||
size_of_tail = 2; | ||
break; | ||
} | ||
if (input[end_headers_i] === 10 && input[end_headers_i + 1] === 13 && input[end_headers_i + 2] === 10) { | ||
size_of_tail = 3; | ||
break; | ||
} | ||
if (input[end_headers_i] === 13 && input[end_headers_i + 1] === 10 && input[end_headers_i + 2] === 10) { | ||
size_of_tail = 3; | ||
break; | ||
} | ||
if (input[end_headers_i] === 13 && input[end_headers_i + 1] === 10 && input[end_headers_i + 2] === 13 && input[end_headers_i + 3] === 10) { | ||
size_of_tail = 4; | ||
break; | ||
} | ||
end_headers_i++; | ||
} | ||
// If no double-newline is found, wait for more input | ||
if (end_headers_i === input.length) { | ||
return null; // Incomplete headers | ||
} | ||
// Extract the header string | ||
const headerBytes = input.slice(begin_headers_i, end_headers_i); | ||
const headerString = new TextDecoder('utf-8').decode(new Uint8Array(headerBytes)); | ||
// Return the remaining bytes and the header string | ||
const remainingBytes = input.slice(end_headers_i + size_of_tail); | ||
return { | ||
remaining_bytes: remainingBytes, | ||
header_string: headerString | ||
}; | ||
} | ||
// **************************** | ||
@@ -707,0 +734,0 @@ // Exports |
@@ -57,3 +57,3 @@ var assert = require('assert') | ||
result += `Content-Length: ${patch.content.length}\r | ||
result += `Content-Length: ${(new TextEncoder().encode(patch.content)).length}\r | ||
Content-Range: ${patch.unit} ${patch.range}\r | ||
@@ -93,8 +93,8 @@ ${Object.entries(extra_headers).map(([k, v]) => `${k}: ${v}\r\n`).join('')}\r | ||
// The contents of the patch is in the request body | ||
var buffer = '' | ||
var buffer = [] | ||
// Read the body one chunk at a time | ||
req.on('data', chunk => buffer = buffer + chunk) | ||
req.on('data', chunk => buffer.push(chunk)) | ||
// Then return it | ||
req.on('end', () => { | ||
patches = [{unit, range, content: buffer}] | ||
patches = [{unit, range, content: Buffer.concat(buffer).toString('utf8')}] | ||
cb(patches) | ||
@@ -108,3 +108,3 @@ }) | ||
let patches = [] | ||
let buffer = "" | ||
let buffer = [] | ||
@@ -119,26 +119,10 @@ // We check to send send patches each time we parse one. But if there | ||
// Merge the latest chunk into our buffer | ||
buffer = (buffer + chunk) | ||
buffer.push(...chunk) | ||
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() | ||
let h = extractHeader(buffer) | ||
if (!h) return | ||
// 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 a set of headers yet. | ||
if (!headers_end) | ||
return | ||
// 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] | ||
// Now let's parse those headers. | ||
var headers = require('parse-headers')( | ||
buffer.substring(0, headers_length) | ||
) | ||
var headers = require('parse-headers')(h.header_string) | ||
@@ -149,3 +133,3 @@ // We require `content-length` to declare the length of the patch. | ||
console.error('No content-length in', JSON.stringify(headers), | ||
'from', {buffer, headers_length}) | ||
'from', {buffer}) | ||
process.exit(1) | ||
@@ -157,3 +141,3 @@ } | ||
// Give up if we don't have the full patch yet. | ||
if (buffer.length < headers_length + blank_line.length + body_length) | ||
if (h.remaining_bytes.length < body_length) | ||
return | ||
@@ -165,5 +149,3 @@ | ||
var [unit, range] = parse_content_range(headers['content-range']) | ||
var patch_content = | ||
buffer.substring(headers_length + blank_line.length, | ||
headers_length + blank_line.length + body_length) | ||
var patch_content = new TextDecoder('utf-8').decode(new Uint8Array(h.remaining_bytes.slice(0, body_length))) | ||
@@ -173,3 +155,3 @@ // We've got our patch! | ||
buffer = buffer.substring(headers_length + blank_line.length + body_length) | ||
buffer = h.remaining_bytes.slice(body_length) | ||
} | ||
@@ -386,3 +368,56 @@ | ||
// a parsing utility function that will inspect a byte array of incoming data | ||
// to see if there is header information at the beginning, | ||
// namely some non-newline characters followed by two newlines | ||
function extractHeader(input) { | ||
// Find the start of the headers | ||
let begin_headers_i = 0; | ||
while (input[begin_headers_i] === 13 || input[begin_headers_i] === 10) { | ||
begin_headers_i++; | ||
} | ||
if (begin_headers_i === input.length) { | ||
return null; // Incomplete headers | ||
} | ||
// Look for the double-newline at the end of the headers | ||
let end_headers_i = begin_headers_i; | ||
let size_of_tail = 0; | ||
while (end_headers_i < input.length) { | ||
if (input[end_headers_i] === 10 && input[end_headers_i + 1] === 10) { | ||
size_of_tail = 2; | ||
break; | ||
} | ||
if (input[end_headers_i] === 10 && input[end_headers_i + 1] === 13 && input[end_headers_i + 2] === 10) { | ||
size_of_tail = 3; | ||
break; | ||
} | ||
if (input[end_headers_i] === 13 && input[end_headers_i + 1] === 10 && input[end_headers_i + 2] === 10) { | ||
size_of_tail = 3; | ||
break; | ||
} | ||
if (input[end_headers_i] === 13 && input[end_headers_i + 1] === 10 && input[end_headers_i + 2] === 13 && input[end_headers_i + 3] === 10) { | ||
size_of_tail = 4; | ||
break; | ||
} | ||
end_headers_i++; | ||
} | ||
// If no double-newline is found, wait for more input | ||
if (end_headers_i === input.length) { | ||
return null; // Incomplete headers | ||
} | ||
// Extract the header string | ||
const headerBytes = input.slice(begin_headers_i, end_headers_i); | ||
const headerString = new TextDecoder('utf-8').decode(new Uint8Array(headerBytes)); | ||
// Return the remaining bytes and the header string | ||
const remainingBytes = input.slice(end_headers_i + size_of_tail); | ||
return { | ||
remaining_bytes: remainingBytes, | ||
header_string: headerString | ||
}; | ||
} | ||
module.exports = braidify |
{ | ||
"name": "braid-http", | ||
"version": "0.3.12", | ||
"version": "0.3.13", | ||
"description": "An implementation of Braid-HTTP for Node.js and Browsers", | ||
@@ -5,0 +5,0 @@ "scripts": { |
47454
959