Compare commits

...

23 Commits

Author SHA1 Message Date
John Hiesey b63537f11d 2.6.3 2017-01-19 03:26:43 -08:00
John Hiesey 11d14fc642 Revert unnecessary part of previous change 2017-01-17 20:23:25 -08:00
John Hiesey 8e1f534a8a Fix Edge fetch errors 2017-01-17 18:39:22 -08:00
John Hiesey c1417c5dfa 2.6.2 2017-01-16 02:00:08 -08:00
John Hiesey 8df10e0d65 Avoid passing undefined to xhr.send()
Provides a more elegant fix to #67
2017-01-16 01:57:32 -08:00
John Hiesey 5ee30ad5cc Fix timeout test failure 2017-01-16 00:35:53 -08:00
John Hiesey 9321e56abd 2.6.1 2017-01-11 23:44:27 -08:00
John Hiesey 881e7c8f3d Merge pull request #65 from jhiesey/csp-xhr-fix
Avoid xhr request to example.com if fetch is supported
2017-01-11 22:44:35 -08:00
Feross Aboukhadijeh 43761f2799 Avoid xhr request to example.com if fetch is supported
For: https://github.com/brave/browser-laptop/issues/5981
2017-01-10 22:17:09 -08:00
John Hiesey 70f8c7d0b7 2.6.0 2017-01-06 01:58:52 -10:00
John Hiesey f304ef13a2 bump builtin-status-codes version 2017-01-06 01:24:15 -10:00
John Hiesey e8ef98b286 style consistency 2017-01-06 01:04:07 -10:00
John Hiesey 3af33f862f Merge pull request #61 from dominictarr/master
if xhr.open throws, then no xhr is allowed
2017-01-06 03:00:46 -08:00
John Hiesey 138d6c1d29 Merge pull request #62 from rlisagor/master
Catching fetch `read()` errors
2017-01-06 02:57:53 -08:00
Roman Lisagor f97dd885ea Catching fetch read() errors
Errors that occur while reading from the ReadableStream that is returned as part of a `fetch` request were not handled. This change propagates these errors up to the `ClientRequest`.
2017-01-04 14:41:01 -08:00
John Hiesey f9fb1c724c Merge pull request #55 from node-influx/master
Support timeout option in http.request
2016-12-27 13:44:03 -08:00
Dominic Tarr 1b077bf249 if xhr.open throws, then no xhr is allowed 2016-12-09 21:04:31 +01:00
John Hiesey e342cdbb10 Merge pull request #59 from mikeal/service-worker
Adding support for Service Workers.
2016-11-16 19:22:00 -08:00
Mikeal Rogers 0a04a09f68 Adding support for Service Workers. 2016-11-16 19:18:19 -08:00
John Hiesey 8c07b21b82 2.5.0 2016-11-03 22:16:57 -07:00
John Hiesey 662b9626be Merge pull request #58 from XiaoningLiu/master
Add payload for Microsoft Azure Storage MERGE method
2016-11-03 22:15:19 -07:00
Xiaoning Liu abdc5573da Add payload for Microsoft Azure Storage MERGE method 2016-11-04 11:35:18 +08:00
Connor Peet 57d0ab245f Support timeout option in http.request 2016-10-17 19:17:44 -07:00
8 changed files with 140 additions and 16 deletions
+4 -2
View File
@@ -94,6 +94,8 @@ the server.
* `message.trailers` and `message.rawTrailers` will remain empty.
* Redirects are followed silently by the browser, so it isn't possible to access the 301/302
redirect pages.
* The `timeout` options in the `request` method is non-operational in Safari <= 5 and
Opera <= 12.
## Example
@@ -101,11 +103,11 @@ redirect pages.
http.get('/bundle.js', function (res) {
var div = document.getElementById('result');
div.innerHTML += 'GET /beep<br>';
res.on('data', function (buf) {
div.innerHTML += buf;
});
res.on('end', function () {
div.innerHTML += '<br>__END__';
});
+36 -7
View File
@@ -6,12 +6,34 @@ try {
exports.blobConstructor = true
} catch (e) {}
var xhr = new global.XMLHttpRequest()
// If XDomainRequest is available (ie only, where xhr might not work
// cross domain), use the page location. Otherwise use example.com
xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')
// The xhr request to example.com may violate some restrictive CSP configurations,
// so if we're running in a browser that supports `fetch`, avoid calling getXHR()
// and assume support for certain features below.
var xhr
function getXHR () {
// Cache the xhr value
if (xhr !== undefined) return xhr
if (global.XMLHttpRequest) {
xhr = new global.XMLHttpRequest()
// If XDomainRequest is available (ie only, where xhr might not work
// cross domain), use the page location. Otherwise use example.com
// Note: this doesn't actually make an http request.
try {
xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')
} catch(e) {
xhr = null
}
} else {
// Service workers don't have XHR
xhr = null
}
return xhr
}
function checkTypeSupport (type) {
var xhr = getXHR()
if (!xhr) return false
try {
xhr.responseType = type
return xhr.responseType === type
@@ -24,17 +46,24 @@ function checkTypeSupport (type) {
var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined'
var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice)
exports.arraybuffer = haveArrayBuffer && checkTypeSupport('arraybuffer')
// If fetch is supported, then arraybuffer will be supported too. Skip calling
// checkTypeSupport(), since that calls getXHR().
exports.arraybuffer = exports.fetch || (haveArrayBuffer && checkTypeSupport('arraybuffer'))
// These next two tests unavoidably show warnings in Chrome. Since fetch will always
// be used if it's available, just return false for these to avoid the warnings.
exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream')
exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer &&
checkTypeSupport('moz-chunked-arraybuffer')
exports.overrideMimeType = isFunction(xhr.overrideMimeType)
// If fetch is supported, then overrideMimeType will be supported too. Skip calling
// getXHR().
exports.overrideMimeType = exports.fetch || (getXHR() ? isFunction(getXHR().overrideMimeType) : false)
exports.vbArray = isFunction(global.VBArray)
function isFunction (value) {
return typeof value === 'function'
return typeof value === 'function'
}
xhr = null // Help gc
+17 -5
View File
@@ -38,8 +38,9 @@ var ClientRequest = module.exports = function (opts) {
var preferBinary
var useFetch = true
if (opts.mode === 'disable-fetch') {
// If the use of XHR should be preferred and includes preserving the 'content-type' header
if (opts.mode === 'disable-fetch' || 'timeout' in opts) {
// If the use of XHR should be preferred and includes preserving the 'content-type' header.
// Force XHR to be used since the Fetch API does not yet support timeouts.
useFetch = false
preferBinary = true
} else if (opts.mode === 'prefer-streaming') {
@@ -97,8 +98,8 @@ ClientRequest.prototype._onFinish = function () {
var opts = self._opts
var headersObj = self._headers
var body
if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH') {
var body = null
if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH' || opts.method === 'MERGE') {
if (capability.blobConstructor) {
body = new global.Blob(self._body.map(function (buffer) {
return toArrayBuffer(buffer)
@@ -119,7 +120,7 @@ ClientRequest.prototype._onFinish = function () {
global.fetch(self._opts.url, {
method: self._opts.method,
headers: headers,
body: body,
body: body || undefined,
mode: 'cors',
credentials: opts.withCredentials ? 'include' : 'same-origin'
}).then(function (response) {
@@ -149,6 +150,13 @@ ClientRequest.prototype._onFinish = function () {
if (self._mode === 'text' && 'overrideMimeType' in xhr)
xhr.overrideMimeType('text/plain; charset=x-user-defined')
if ('timeout' in opts) {
xhr.timeout = opts.timeout
xhr.ontimeout = function () {
self.emit('timeout')
}
}
Object.keys(headersObj).forEach(function (name) {
xhr.setRequestHeader(headersObj[name].name, headersObj[name].value)
})
@@ -220,6 +228,10 @@ ClientRequest.prototype._connect = function () {
return
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode)
self._response.on('error', function(err) {
self.emit('error', err)
})
self.emit('response', self._response)
}
+2
View File
@@ -53,6 +53,8 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
}
self.push(new Buffer(result.value))
read()
}).catch(function(err) {
self.emit('error', err)
})
}
read()
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "stream-http",
"version": "2.4.1",
"version": "2.6.3",
"description": "Streaming http in the browser",
"main": "index.js",
"repository": {
@@ -27,7 +27,7 @@
"http-browserify"
],
"dependencies": {
"builtin-status-codes": "^2.0.0",
"builtin-status-codes": "^3.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.1.0",
"to-arraybuffer": "^1.0.0",
+29
View File
@@ -0,0 +1,29 @@
var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var http = require('../..')
var reference = fs.readFileSync(__dirname + '/../server/static/basic.txt')
test('delete empty', function (t) {
var req = http.request({
path: '/verifyEmpty',
method: 'DELETE'
}, function (res) {
var buffers = []
res.on('end', function () {
console.log(Buffer.concat(buffers).toString('utf8'))
t.ok(Buffer.from('empty').equals(Buffer.concat(buffers)), 'response body indicates request body was empty')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
req.write(reference)
req.end()
})
+32
View File
@@ -0,0 +1,32 @@
var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var UAParser = require('ua-parser-js')
var url = require('url')
var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
var skipTimeout = ((browserName === 'Opera' && browserVersion <= 12) ||
(browserName === 'Safari' && browserVersion <= 5))
test('emits timeout events', function (t) {
if (skipTimeout) {
return t.skip('Browser does not support setting timeouts')
}
var req = http.request({
path: '/basic.txt',
timeout: 1
})
req.on('timeout', function () {
t.end() // the test will timeout if this does not happen
})
req.end()
})
+18
View File
@@ -71,6 +71,24 @@ app.post('/echo', function (req, res) {
req.pipe(res)
})
app.use('/verifyEmpty', function (req, res) {
var empty = true
req.on('data', function (buf) {
if (buf.length > 0) {
empty = false
}
})
req.on('end', function () {
res.setHeader('Content-Type', 'text/plain')
if (empty) {
res.end('empty')
} else {
res.end('not empty')
}
})
})
app.use(function (req, res, next) {
var parsed = url.parse(req.url, true)