chrome-https
Advanced tools
Comparing version 1.0.0 to 2.0.0
149
chrome.js
@@ -0,146 +1,13 @@ | ||
var http = require('./http'); | ||
var https = module.exports; | ||
var EventEmitter = require('events').EventEmitter; | ||
var Request = require('./lib/request'); | ||
var url = require('url') | ||
for (var key in http) { | ||
if (http.hasOwnProperty(key)) https[key] = http[key]; | ||
}; | ||
https.request = function (params, cb) { | ||
if (typeof params === 'string') { | ||
params = url.parse(params) | ||
} | ||
if (!params) params = {}; | ||
params.scheme = 'https'; | ||
if (!params.host && !params.port) { | ||
params.port = parseInt(window.location.port, 10); | ||
} | ||
if (!params.host && params.hostname) { | ||
params.host = params.hostname; | ||
} | ||
if (!params.protocol) { | ||
if (params.scheme) { | ||
params.protocol = params.scheme + ':'; | ||
} else { | ||
params.protocol = window.location.protocol; | ||
} | ||
} | ||
if (!params.host) { | ||
params.host = window.location.hostname || window.location.host; | ||
} | ||
if (/:/.test(params.host)) { | ||
if (!params.port) { | ||
params.port = params.host.split(':')[1]; | ||
} | ||
params.host = params.host.split(':')[0]; | ||
} | ||
if (!params.port) params.port = params.protocol == 'https:' ? 443 : 80; | ||
var req = new Request(new xhrHttp, params); | ||
if (cb) req.on('response', cb); | ||
return req; | ||
}; | ||
https.get = function (params, cb) { | ||
params.method = 'GET'; | ||
var req = https.request(params, cb); | ||
req.end(); | ||
return req; | ||
}; | ||
https.Agent = function () {}; | ||
https.Agent.defaultMaxSockets = 4; | ||
var xhrHttp = (function () { | ||
if (typeof window === 'undefined') { | ||
throw new Error('no window object present'); | ||
} | ||
else if (window.XMLHttpRequest) { | ||
return window.XMLHttpRequest; | ||
} | ||
else if (window.ActiveXObject) { | ||
var axs = [ | ||
'Msxml2.XMLhttps.6.0', | ||
'Msxml2.XMLhttps.3.0', | ||
'Microsoft.XMLHTTP' | ||
]; | ||
for (var i = 0; i < axs.length; i++) { | ||
try { | ||
var ax = new(window.ActiveXObject)(axs[i]); | ||
return function () { | ||
if (ax) { | ||
var ax_ = ax; | ||
ax = null; | ||
return ax_; | ||
} | ||
else { | ||
return new(window.ActiveXObject)(axs[i]); | ||
} | ||
}; | ||
} | ||
catch (e) {} | ||
} | ||
throw new Error('ajax not supported in this browser') | ||
} | ||
else { | ||
throw new Error('ajax not supported in this browser'); | ||
} | ||
})(); | ||
https.STATUS_CODES = { | ||
100 : 'Continue', | ||
101 : 'Switching Protocols', | ||
102 : 'Processing', // RFC 2518, obsoleted by RFC 4918 | ||
200 : 'OK', | ||
201 : 'Created', | ||
202 : 'Accepted', | ||
203 : 'Non-Authoritative Information', | ||
204 : 'No Content', | ||
205 : 'Reset Content', | ||
206 : 'Partial Content', | ||
207 : 'Multi-Status', // RFC 4918 | ||
300 : 'Multiple Choices', | ||
301 : 'Moved Permanently', | ||
302 : 'Moved Temporarily', | ||
303 : 'See Other', | ||
304 : 'Not Modified', | ||
305 : 'Use Proxy', | ||
307 : 'Temporary Redirect', | ||
400 : 'Bad Request', | ||
401 : 'Unauthorized', | ||
402 : 'Payment Required', | ||
403 : 'Forbidden', | ||
404 : 'Not Found', | ||
405 : 'Method Not Allowed', | ||
406 : 'Not Acceptable', | ||
407 : 'Proxy Authentication Required', | ||
408 : 'Request Time-out', | ||
409 : 'Conflict', | ||
410 : 'Gone', | ||
411 : 'Length Required', | ||
412 : 'Precondition Failed', | ||
413 : 'Request Entity Too Large', | ||
414 : 'Request-URI Too Large', | ||
415 : 'Unsupported Media Type', | ||
416 : 'Requested Range Not Satisfiable', | ||
417 : 'Expectation Failed', | ||
418 : 'I\'m a teapot', // RFC 2324 | ||
422 : 'Unprocessable Entity', // RFC 4918 | ||
423 : 'Locked', // RFC 4918 | ||
424 : 'Failed Dependency', // RFC 4918 | ||
425 : 'Unordered Collection', // RFC 4918 | ||
426 : 'Upgrade Required', // RFC 2817 | ||
428 : 'Precondition Required', // RFC 6585 | ||
429 : 'Too Many Requests', // RFC 6585 | ||
431 : 'Request Header Fields Too Large',// RFC 6585 | ||
500 : 'Internal Server Error', | ||
501 : 'Not Implemented', | ||
502 : 'Bad Gateway', | ||
503 : 'Service Unavailable', | ||
504 : 'Gateway Time-out', | ||
505 : 'HTTP Version Not Supported', | ||
506 : 'Variant Also Negotiates', // RFC 2295 | ||
507 : 'Insufficient Storage', // RFC 4918 | ||
509 : 'Bandwidth Limit Exceeded', | ||
510 : 'Not Extended', // RFC 2774 | ||
511 : 'Network Authentication Required' // RFC 6585 | ||
}; | ||
return http.request.call(this, params, cb); | ||
} |
@@ -1,209 +0,280 @@ | ||
var Stream = require('stream'); | ||
var Response = require('./response'); | ||
var Base64 = require('Base64'); | ||
var inherits = require('inherits'); | ||
var capability = require('./capability') | ||
var foreach = require('foreach') | ||
var indexOf = require('indexof') | ||
var inherits = require('inherits') | ||
var keys = require('object-keys') | ||
var response = require('./response') | ||
var stream = require('stream') | ||
var Request = module.exports = function (xhr, params) { | ||
var self = this; | ||
self.writable = true; | ||
self.xhr = xhr; | ||
self.body = []; | ||
self.uri = (params.protocol || 'http:') + '//' | ||
+ params.host | ||
+ (params.port ? ':' + params.port : '') | ||
+ (params.path || '/') | ||
; | ||
if (typeof params.withCredentials === 'undefined') { | ||
params.withCredentials = true; | ||
} | ||
var IncomingMessage = response.IncomingMessage | ||
var rStates = response.readyStates | ||
try { xhr.withCredentials = params.withCredentials } | ||
catch (e) {} | ||
if (params.responseType) try { xhr.responseType = params.responseType } | ||
catch (e) {} | ||
xhr.open( | ||
params.method || 'GET', | ||
self.uri, | ||
true | ||
); | ||
function decideMode (preferBinary) { | ||
if (capability.fetch) { | ||
return 'fetch' | ||
} else if (capability.mozchunkedarraybuffer) { | ||
return 'moz-chunked-arraybuffer' | ||
} else if (capability.msstream) { | ||
return 'ms-stream' | ||
} else if (capability.arraybuffer && preferBinary) { | ||
return 'arraybuffer' | ||
} else if (capability.vbArray && preferBinary) { | ||
return 'text:vbarray' | ||
} else { | ||
return 'text' | ||
} | ||
} | ||
xhr.onerror = function(event) { | ||
self.emit('error', new Error('Network error')); | ||
}; | ||
var ClientRequest = module.exports = function (opts) { | ||
var self = this | ||
stream.Writable.call(self) | ||
self._headers = {}; | ||
if (params.headers) { | ||
var keys = objectKeys(params.headers); | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
if (!self.isSafeRequestHeader(key)) continue; | ||
var value = params.headers[key]; | ||
self.setHeader(key, value); | ||
} | ||
} | ||
if (params.auth) { | ||
//basic auth | ||
this.setHeader('Authorization', 'Basic ' + Base64.btoa(params.auth)); | ||
} | ||
self._opts = opts | ||
self._url = opts.protocol + '//' + opts.hostname + ':' + opts.port + opts.path | ||
self._body = [] | ||
self._headers = {} | ||
if (opts.auth) | ||
self.setHeader('Authorization', 'Basic ' + new Buffer(opts.auth).toString('base64')) | ||
foreach(keys(opts.headers), function (name) { | ||
self.setHeader(name, opts.headers[name]) | ||
}) | ||
var res = new Response; | ||
res.on('close', function () { | ||
self.emit('close'); | ||
}); | ||
res.on('ready', function () { | ||
self.emit('response', res); | ||
}); | ||
var preferBinary | ||
if (opts.mode === 'prefer-streaming') { | ||
// If streaming is a high priority but binary compatibility isn't | ||
preferBinary = false | ||
} else if (opts.mode === 'prefer-fast') { | ||
// If binary is preferred for speed | ||
preferBinary = true | ||
} else if (!opts.mode || opts.mode === 'default') { | ||
// By default, use binary if text streaming may corrupt data | ||
preferBinary = !capability.overrideMimeType | ||
} else { | ||
throw new Error('Invalid value for opts.mode') | ||
} | ||
self._mode = decideMode(preferBinary) | ||
res.on('error', function (err) { | ||
self.emit('error', err); | ||
}); | ||
xhr.onreadystatechange = function () { | ||
// Fix for IE9 bug | ||
// SCRIPT575: Could not complete the operation due to error c00c023f | ||
// It happens when a request is aborted, calling the success callback anyway with readyState === 4 | ||
if (xhr.__aborted) return; | ||
res.handle(xhr); | ||
}; | ||
}; | ||
self.on('finish', function () { | ||
self._onFinish() | ||
}) | ||
} | ||
inherits(Request, Stream); | ||
inherits(ClientRequest, stream.Writable) | ||
Request.prototype.setHeader = function (key, value) { | ||
this._headers[key.toLowerCase()] = value | ||
}; | ||
ClientRequest.prototype.setHeader = function (name, value) { | ||
var self = this | ||
var lowerName = name.toLowerCase() | ||
// This check is not necessary, but it prevents warnings from browsers about setting unsafe | ||
// headers. To be honest I'm not entirely sure hiding these warnings is a good thing, but | ||
// http-browserify did it, so I will too. | ||
if (indexOf(unsafeHeaders, lowerName) !== -1) | ||
return | ||
Request.prototype.getHeader = function (key) { | ||
return this._headers[key.toLowerCase()] | ||
}; | ||
self._headers[lowerName] = { | ||
name: name, | ||
value: value | ||
} | ||
} | ||
Request.prototype.removeHeader = function (key) { | ||
delete this._headers[key.toLowerCase()] | ||
}; | ||
ClientRequest.prototype.getHeader = function (name) { | ||
var self = this | ||
return self._headers[name.toLowerCase()].value | ||
} | ||
Request.prototype.write = function (s) { | ||
this.body.push(s); | ||
}; | ||
ClientRequest.prototype.removeHeader = function (name) { | ||
var self = this | ||
delete self._headers[name.toLowerCase()] | ||
} | ||
Request.prototype.destroy = function (s) { | ||
this.xhr.__aborted = true; | ||
this.xhr.abort(); | ||
this.emit('close'); | ||
}; | ||
ClientRequest.prototype._onFinish = function () { | ||
var self = this | ||
Request.prototype.end = function (s) { | ||
if (s !== undefined) this.body.push(s); | ||
if (self._destroyed) | ||
return | ||
var opts = self._opts | ||
var keys = objectKeys(this._headers); | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = this._headers[key]; | ||
if (isArray(value)) { | ||
for (var j = 0; j < value.length; j++) { | ||
this.xhr.setRequestHeader(key, value[j]); | ||
} | ||
} | ||
else this.xhr.setRequestHeader(key, value) | ||
} | ||
var headersObj = self._headers | ||
var body | ||
if (opts.method === 'POST' || opts.method === 'PUT') { | ||
if (capability.blobConstructor) { | ||
body = new window.Blob(self._body.map(function (buffer) { | ||
return buffer.toArrayBuffer() | ||
}), { | ||
type: (headersObj['content-type'] || {}).value || '' | ||
}) | ||
} else { | ||
// get utf8 string | ||
body = Buffer.concat(self._body).toString() | ||
} | ||
} | ||
if (this.body.length === 0) { | ||
this.xhr.send(''); | ||
} | ||
else if (typeof this.body[0] === 'string') { | ||
this.xhr.send(this.body.join('')); | ||
} | ||
else if (isArray(this.body[0])) { | ||
var body = []; | ||
for (var i = 0; i < this.body.length; i++) { | ||
body.push.apply(body, this.body[i]); | ||
} | ||
this.xhr.send(body); | ||
} | ||
else if (/Array/.test(Object.prototype.toString.call(this.body[0]))) { | ||
var len = 0; | ||
for (var i = 0; i < this.body.length; i++) { | ||
len += this.body[i].length; | ||
} | ||
var body = new(this.body[0].constructor)(len); | ||
var k = 0; | ||
for (var i = 0; i < this.body.length; i++) { | ||
var b = this.body[i]; | ||
for (var j = 0; j < b.length; j++) { | ||
body[k++] = b[j]; | ||
} | ||
} | ||
this.xhr.send(body); | ||
} | ||
else if (isXHR2Compatible(this.body[0])) { | ||
this.xhr.send(this.body[0]); | ||
} | ||
else { | ||
var body = ''; | ||
for (var i = 0; i < this.body.length; i++) { | ||
body += this.body[i].toString(); | ||
} | ||
this.xhr.send(body); | ||
} | ||
}; | ||
if (self._mode === 'fetch') { | ||
var headers = keys(headersObj).map(function (name) { | ||
return [headersObj[name].name, headersObj[name].value] | ||
}) | ||
// Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html | ||
Request.unsafeHeaders = [ | ||
"accept-charset", | ||
"accept-encoding", | ||
"access-control-request-headers", | ||
"access-control-request-method", | ||
"connection", | ||
"content-length", | ||
"cookie", | ||
"cookie2", | ||
"content-transfer-encoding", | ||
"date", | ||
"expect", | ||
"host", | ||
"keep-alive", | ||
"origin", | ||
"referer", | ||
"te", | ||
"trailer", | ||
"transfer-encoding", | ||
"upgrade", | ||
"user-agent", | ||
"via" | ||
]; | ||
window.fetch(self._url, { | ||
method: self._opts.method, | ||
headers: headers, | ||
body: body, | ||
mode: 'cors', | ||
credentials: opts.withCredentials ? 'include' : 'same-origin' | ||
}).then(function (response) { | ||
self._fetchResponse = response | ||
self._connect() | ||
}).then(undefined, function (reason) { | ||
self.emit('error', reason) | ||
}) | ||
} else { | ||
var xhr = self._xhr = new window.XMLHttpRequest() | ||
try { | ||
xhr.open(self._opts.method, self._url, true) | ||
} catch (err) { | ||
process.nextTick(function () { | ||
self.emit('error', err) | ||
}) | ||
return | ||
} | ||
Request.prototype.isSafeRequestHeader = function (headerName) { | ||
if (!headerName) return false; | ||
return indexOf(Request.unsafeHeaders, headerName.toLowerCase()) === -1; | ||
}; | ||
// Can't set responseType on really old browsers | ||
if ('responseType' in xhr) | ||
xhr.responseType = self._mode.split(':')[0] | ||
var objectKeys = Object.keys || function (obj) { | ||
var keys = []; | ||
for (var key in obj) keys.push(key); | ||
return keys; | ||
}; | ||
if ('withCredentials' in xhr) | ||
xhr.withCredentials = !!opts.withCredentials | ||
var isArray = Array.isArray || function (xs) { | ||
return Object.prototype.toString.call(xs) === '[object Array]'; | ||
}; | ||
if (self._mode === 'text' && 'overrideMimeType' in xhr) | ||
xhr.overrideMimeType('text/plain; charset=x-user-defined') | ||
var indexOf = function (xs, x) { | ||
if (xs.indexOf) return xs.indexOf(x); | ||
for (var i = 0; i < xs.length; i++) { | ||
if (xs[i] === x) return i; | ||
} | ||
return -1; | ||
}; | ||
foreach(keys(headersObj), function (name) { | ||
xhr.setRequestHeader(headersObj[name].name, headersObj[name].value) | ||
}) | ||
var isXHR2Compatible = function (obj) { | ||
if (typeof Blob !== 'undefined' && obj instanceof Blob) return true; | ||
if (typeof ArrayBuffer !== 'undefined' && obj instanceof ArrayBuffer) return true; | ||
if (typeof FormData !== 'undefined' && obj instanceof FormData) return true; | ||
}; | ||
self._response = null | ||
xhr.onreadystatechange = function () { | ||
switch (xhr.readyState) { | ||
case rStates.LOADING: | ||
case rStates.DONE: | ||
self._onXHRProgress() | ||
break | ||
} | ||
} | ||
// Necessary for streaming in Firefox, since xhr.response is ONLY defined | ||
// in onprogress, not in onreadystatechange with xhr.readyState = 3 | ||
if (self._mode === 'moz-chunked-arraybuffer') { | ||
xhr.onprogress = function () { | ||
self._onXHRProgress() | ||
} | ||
} | ||
xhr.onerror = function () { | ||
if (self._destroyed) | ||
return | ||
self.emit('error', new Error('XHR error')) | ||
} | ||
try { | ||
xhr.send(body) | ||
} catch (err) { | ||
process.nextTick(function () { | ||
self.emit('error', err) | ||
}) | ||
return | ||
} | ||
} | ||
} | ||
/** | ||
* Checks if xhr.status is readable. Even though the spec says it should | ||
* be available in readyState 3, accessing it throws an exception in IE8 | ||
*/ | ||
function statusValid (xhr) { | ||
try { | ||
return (xhr.status !== null) | ||
} catch (e) { | ||
return false | ||
} | ||
} | ||
ClientRequest.prototype._onXHRProgress = function () { | ||
var self = this | ||
if (!statusValid(self._xhr) || self._destroyed) | ||
return | ||
if (!self._response) | ||
self._connect() | ||
self._response._onXHRProgress() | ||
} | ||
ClientRequest.prototype._connect = function () { | ||
var self = this | ||
if (self._destroyed) | ||
return | ||
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode) | ||
self.emit('response', self._response) | ||
} | ||
ClientRequest.prototype._write = function (chunk, encoding, cb) { | ||
var self = this | ||
self._body.push(chunk) | ||
cb() | ||
} | ||
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () { | ||
var self = this | ||
self._destroyed = true | ||
if (self._response) | ||
self._response._destroyed = true | ||
if (self._xhr) | ||
self._xhr.abort() | ||
// Currently, there isn't a way to truly abort a fetch. | ||
// If you like bikeshedding, see https://github.com/whatwg/fetch/issues/27 | ||
} | ||
ClientRequest.prototype.end = function (data, encoding, cb) { | ||
var self = this | ||
if (typeof data === 'function') { | ||
cb = data | ||
data = undefined | ||
} | ||
if (data) | ||
stream.Writable.push.call(self, data, encoding) | ||
stream.Writable.prototype.end.call(self, cb) | ||
} | ||
ClientRequest.prototype.flushHeaders = function () {} | ||
ClientRequest.prototype.setTimeout = function () {} | ||
ClientRequest.prototype.setNoDelay = function () {} | ||
ClientRequest.prototype.setSocketKeepAlive = function () {} | ||
// Taken from http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method | ||
var unsafeHeaders = [ | ||
'accept-charset', | ||
'accept-encoding', | ||
'access-control-request-headers', | ||
'access-control-request-method', | ||
'connection', | ||
'content-length', | ||
'cookie', | ||
'cookie2', | ||
'date', | ||
'dnt', | ||
'expect', | ||
'host', | ||
'keep-alive', | ||
'origin', | ||
'referer', | ||
'te', | ||
'trailer', | ||
'transfer-encoding', | ||
'upgrade', | ||
'user-agent', | ||
'via' | ||
] |
@@ -1,120 +0,173 @@ | ||
var Stream = require('stream'); | ||
var util = require('util'); | ||
var capability = require('./capability') | ||
var foreach = require('foreach') | ||
var inherits = require('inherits') | ||
var stream = require('stream') | ||
var Response = module.exports = function (res) { | ||
this.offset = 0; | ||
this.readable = true; | ||
}; | ||
var rStates = exports.readyStates = { | ||
UNSENT: 0, | ||
OPENED: 1, | ||
HEADERS_RECEIVED: 2, | ||
LOADING: 3, | ||
DONE: 4 | ||
} | ||
util.inherits(Response, Stream); | ||
var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) { | ||
var self = this | ||
stream.Readable.call(self) | ||
var capable = { | ||
streaming : true, | ||
status2 : true | ||
}; | ||
self._mode = mode | ||
self.headers = {} | ||
self.rawHeaders = [] | ||
self.trailers = {} | ||
self.rawTrailers = [] | ||
function parseHeaders (res) { | ||
var lines = res.getAllResponseHeaders().split(/\r?\n/); | ||
var headers = {}; | ||
for (var i = 0; i < lines.length; i++) { | ||
var line = lines[i]; | ||
if (line === '') continue; | ||
var m = line.match(/^([^:]+):\s*(.*)/); | ||
if (m) { | ||
var key = m[1].toLowerCase(), value = m[2]; | ||
if (headers[key] !== undefined) { | ||
if (isArray(headers[key])) { | ||
headers[key].push(value); | ||
} | ||
else { | ||
headers[key] = [ headers[key], value ]; | ||
} | ||
} | ||
else { | ||
headers[key] = value; | ||
} | ||
} | ||
else { | ||
headers[line] = true; | ||
} | ||
} | ||
return headers; | ||
} | ||
// Fake the 'close' event, but only once 'end' fires | ||
self.on('end', function () { | ||
// The nextTick is necessary to prevent the 'request' module from causing an infinite loop | ||
process.nextTick(function () { | ||
self.emit('close') | ||
}) | ||
}) | ||
Response.prototype.getResponse = function (xhr) { | ||
var respType = String(xhr.responseType).toLowerCase(); | ||
if (respType === 'blob') return xhr.responseBlob || xhr.response; | ||
if (respType === 'arraybuffer') return xhr.response; | ||
return xhr.responseText; | ||
if (mode === 'fetch') { | ||
self._fetchResponse = response | ||
self.statusCode = response.status | ||
self.statusMessage = response.statusText | ||
// backwards compatible version of for (<item> of <iterable>): | ||
// for (var <item>,_i,_it = <iterable>[Symbol.iterator](); <item> = (_i = _it.next()).value,!_i.done;) | ||
for (var header, _i, _it = response.headers[Symbol.iterator](); header = (_i = _it.next()).value, !_i.done;) { | ||
self.headers[header[0].toLowerCase()] = header[1] | ||
self.rawHeaders.push(header[0], header[1]) | ||
} | ||
// TODO: this doesn't respect backpressure. Once WritableStream is available, this can be fixed | ||
var reader = response.body.getReader() | ||
function read () { | ||
reader.read().then(function (result) { | ||
if (self._destroyed) | ||
return | ||
if (result.done) { | ||
self.push(null) | ||
return | ||
} | ||
self.push(new Buffer(result.value)) | ||
read() | ||
}) | ||
} | ||
read() | ||
} else { | ||
self._xhr = xhr | ||
self._pos = 0 | ||
self.statusCode = xhr.status | ||
self.statusMessage = xhr.statusText | ||
var headers = xhr.getAllResponseHeaders().split(/\r?\n/) | ||
foreach(headers, function (header) { | ||
var matches = header.match(/^([^:]+):\s*(.*)/) | ||
if (matches) { | ||
var key = matches[1].toLowerCase() | ||
if (self.headers[key] !== undefined) | ||
self.headers[key] += ', ' + matches[2] | ||
else | ||
self.headers[key] = matches[2] | ||
self.rawHeaders.push(matches[1], matches[2]) | ||
} | ||
}) | ||
self._charset = 'x-user-defined' | ||
if (!capability.overrideMimeType) { | ||
var mimeType = self.rawHeaders['mime-type'] | ||
if (mimeType) { | ||
var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/) | ||
if (charsetMatch) { | ||
self._charset = charsetMatch[1].toLowerCase() | ||
} | ||
} | ||
if (!self._charset) | ||
self._charset = 'utf-8' // best guess | ||
} | ||
} | ||
} | ||
Response.prototype.getHeader = function (key) { | ||
return this.headers[key.toLowerCase()]; | ||
}; | ||
inherits(IncomingMessage, stream.Readable) | ||
Response.prototype.handle = function (res) { | ||
if (res.readyState === 2 && capable.status2) { | ||
try { | ||
this.statusCode = res.status; | ||
this.headers = parseHeaders(res); | ||
} | ||
catch (err) { | ||
capable.status2 = false; | ||
} | ||
if (capable.status2) { | ||
this.emit('ready'); | ||
} | ||
} | ||
else if (capable.streaming && res.readyState === 3) { | ||
try { | ||
if (!this.statusCode) { | ||
this.statusCode = res.status; | ||
this.headers = parseHeaders(res); | ||
this.emit('ready'); | ||
} | ||
} | ||
catch (err) {} | ||
try { | ||
this._emitData(res); | ||
} | ||
catch (err) { | ||
capable.streaming = false; | ||
} | ||
} | ||
else if (res.readyState === 4) { | ||
if (!this.statusCode) { | ||
this.statusCode = res.status; | ||
this.emit('ready'); | ||
} | ||
this._emitData(res); | ||
if (res.error) { | ||
this.emit('error', this.getResponse(res)); | ||
} | ||
else this.emit('end'); | ||
this.emit('close'); | ||
} | ||
}; | ||
IncomingMessage.prototype._read = function () {} | ||
Response.prototype._emitData = function (res) { | ||
var respBody = this.getResponse(res); | ||
if (respBody.toString().match(/ArrayBuffer/)) { | ||
this.emit('data', new Uint8Array(respBody, this.offset)); | ||
this.offset = respBody.byteLength; | ||
return; | ||
} | ||
if (respBody.length > this.offset) { | ||
this.emit('data', respBody.slice(this.offset)); | ||
this.offset = respBody.length; | ||
} | ||
}; | ||
IncomingMessage.prototype._onXHRProgress = function () { | ||
var self = this | ||
var isArray = Array.isArray || function (xs) { | ||
return Object.prototype.toString.call(xs) === '[object Array]'; | ||
}; | ||
var xhr = self._xhr | ||
var response = null | ||
switch (self._mode) { | ||
case 'text:vbarray': // For IE9 | ||
if (xhr.readyState !== rStates.DONE) | ||
break | ||
try { | ||
// This fails in IE8 | ||
response = new window.VBArray(xhr.responseBody).toArray() | ||
} catch (e) {} | ||
if (response !== null) { | ||
self.push(new Buffer(response)) | ||
break | ||
} | ||
// Falls through in IE8 | ||
case 'text': | ||
try { // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4 | ||
response = xhr.responseText | ||
} catch (e) { | ||
self._mode = 'text:vbarray' | ||
break | ||
} | ||
if (response.length > self._pos) { | ||
var newData = response.substr(self._pos) | ||
if (self._charset === 'x-user-defined') { | ||
var buffer = new Buffer(newData.length) | ||
for (var i = 0; i < newData.length; i++) | ||
buffer[i] = newData.charCodeAt(i) & 0xff | ||
self.push(buffer) | ||
} else { | ||
self.push(newData, self._charset) | ||
} | ||
self._pos = response.length | ||
} | ||
break | ||
case 'arraybuffer': | ||
if (xhr.readyState !== rStates.DONE) | ||
break | ||
response = xhr.response | ||
self.push(new Buffer(new Uint8Array(response))) | ||
break | ||
case 'moz-chunked-arraybuffer': // take whole | ||
response = xhr.response | ||
if (xhr.readyState !== rStates.LOADING || !response) | ||
break | ||
self.push(new Buffer(new Uint8Array(response))) | ||
break | ||
case 'ms-stream': | ||
response = xhr.response | ||
if (xhr.readyState !== rStates.LOADING) | ||
break | ||
var reader = new window.MSStreamReader() | ||
reader.onprogress = function () { | ||
if (reader.result.byteLength > self._pos) { | ||
self.push(new Buffer(new Uint8Array(reader.result.slice(self._pos)))) | ||
self._pos = reader.result.byteLength | ||
} | ||
} | ||
reader.onload = function () { | ||
self.push(null) | ||
} | ||
// reader.onerror = ??? // TODO: this | ||
reader.readAsArrayBuffer(response) | ||
break | ||
} | ||
// The ms-stream case handles end separately in reader.onload() | ||
if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') { | ||
self.push(null) | ||
} | ||
} |
{ | ||
"name": "chrome-https", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "https module compatability for chrome apps", | ||
@@ -16,7 +16,12 @@ "main": "main.js", | ||
"dependencies": { | ||
"Base64": "~0.2.0", | ||
"inherits": "~2.0.1" | ||
"builtin-status-codes": "~1.0.0", | ||
"foreach": "^2.0.5", | ||
"indexof": "0.0.1", | ||
"inherits": "^2.0.1", | ||
"object-keys": "1.0.4", | ||
"xtend": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"launch-chrome-app": "^1.0.1" | ||
"launch-chrome-app": "^1.0.1", | ||
"through2": "^2.0.0" | ||
}, | ||
@@ -23,0 +28,0 @@ "repository": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19989
10
472
123
6
2
2
+ Addedbuiltin-status-codes@~1.0.0
+ Addedforeach@^2.0.5
+ Addedindexof@0.0.1
+ Addedobject-keys@1.0.4
+ Addedxtend@^4.0.0
+ Addedbuiltin-status-codes@1.0.0(transitive)
+ Addedforeach@2.0.6(transitive)
+ Addedindexof@0.0.1(transitive)
+ Addedobject-keys@1.0.4(transitive)
+ Addedxtend@4.0.2(transitive)
- RemovedBase64@~0.2.0
- RemovedBase64@0.2.1(transitive)
Updatedinherits@^2.0.1