hijackresponse
Advanced tools
Comparing version 3.0.0 to 4.0.0
@@ -1,115 +0,125 @@ | ||
var Readable = require('stream').Readable | ||
var Readable = require("stream").Readable; | ||
module.exports = function hijackResponse (res, cb) { | ||
var writeHead = res.writeHead | ||
var write = res.write | ||
var end = res.end | ||
var originalResponse = res | ||
var hijacking = true | ||
var hijackedResponse = new Readable() | ||
hijackedResponse.__proto__ = originalResponse // eslint-disable-line no-proto | ||
hijackedResponse.emit = hijackedResponse.emit | ||
module.exports = function hijackResponse(res, cb) { | ||
var writeHead = res.writeHead; | ||
var write = res.write; | ||
var end = res.end; | ||
var originalResponse = res; | ||
var hijacking = true; | ||
var hijackedResponse = new Readable(); | ||
hijackedResponse.__proto__ = originalResponse; // eslint-disable-line no-proto | ||
var readableMethods = Object.keys(Readable.prototype) | ||
readableMethods.forEach(function (method) { | ||
hijackedResponse[method] = Readable.prototype[method].bind(hijackedResponse) | ||
}) | ||
var readableMethods = Object.keys(Readable.prototype); | ||
hijackedResponse._read = function () {} | ||
// emit is not included when doing Object.keys on the prototype, but we need | ||
// it. | ||
readableMethods.push("emit"); | ||
res.write = function (rawChunk, encoding) { | ||
if (!res.headersSent && res.writeHead !== writeHead) res._implicitHeader() | ||
readableMethods.forEach(function(method) { | ||
hijackedResponse[method] = Readable.prototype[method].bind( | ||
hijackedResponse | ||
); | ||
}); | ||
hijackedResponse._read = function() {}; | ||
res.write = function(rawChunk, encoding) { | ||
if (!res.headersSent && res.writeHead !== writeHead) res._implicitHeader(); | ||
if (hijacking) { | ||
var chunk = rawChunk | ||
if (rawChunk !== null && !Buffer.isBuffer(chunk) && encoding !== 'buffer') { | ||
var chunk = rawChunk; | ||
if ( | ||
rawChunk !== null && | ||
!Buffer.isBuffer(chunk) && | ||
encoding !== "buffer" | ||
) { | ||
if (!encoding) { | ||
chunk = new Buffer(rawChunk) | ||
chunk = new Buffer(rawChunk); | ||
} else { | ||
chunk = new Buffer(rawChunk, encoding) | ||
chunk = new Buffer(rawChunk, encoding); | ||
} | ||
} | ||
hijackedResponse.push(chunk) | ||
hijackedResponse.push(chunk); | ||
} else { | ||
write.call(originalResponse, rawChunk, encoding) | ||
write.call(originalResponse, rawChunk, encoding); | ||
} | ||
} | ||
}; | ||
res.end = function (chunk, encoding) { | ||
res.end = function(chunk, encoding) { | ||
if (chunk) { | ||
res.write(chunk, encoding) | ||
res.write(chunk, encoding); | ||
} else if (!res.headersSent && res.writeHead !== writeHead) { | ||
res._implicitHeader() | ||
res._implicitHeader(); | ||
} | ||
if (hijacking) { | ||
hijackedResponse.push(null) | ||
hijackedResponse.push(null); | ||
} else { | ||
end.call(originalResponse) | ||
end.call(originalResponse); | ||
} | ||
} | ||
}; | ||
var resEmit = res.emit | ||
res.emit = function (eventName) { | ||
if (eventName === 'close') { | ||
hijackedResponse.emit('close') | ||
var resEmit = res.emit; | ||
res.emit = function(eventName) { | ||
if (eventName === "close") { | ||
hijackedResponse.emit("close"); | ||
} | ||
return resEmit.apply(this, arguments) | ||
} | ||
return resEmit.apply(this, arguments); | ||
}; | ||
hijackedResponse.destroyHijacked = function () { | ||
res.write = res.end = function () {} | ||
hijackedResponse._readableState.buffer = [] | ||
return resEmit.call(res, 'close') | ||
} | ||
hijackedResponse.destroyHijacked = function() { | ||
res.write = res.end = function() {}; | ||
hijackedResponse._readableState.buffer = []; | ||
return resEmit.call(res, "close"); | ||
}; | ||
hijackedResponse.write = function (chunk, encoding) { | ||
write.call(originalResponse, chunk, encoding) | ||
} | ||
hijackedResponse.write = function(chunk, encoding) { | ||
write.call(originalResponse, chunk, encoding); | ||
}; | ||
hijackedResponse.end = function (chunk, encoding) { | ||
hijackedResponse.end = function(chunk, encoding) { | ||
if (chunk) { | ||
write.call(originalResponse, chunk, encoding) | ||
write.call(originalResponse, chunk, encoding); | ||
} | ||
if (hijacking) { | ||
end.call(originalResponse) | ||
end.call(originalResponse); | ||
} else { | ||
// If unhijacked, delay end-event so pipes don't close too early giving | ||
// you a chance to have error handlers work. | ||
setImmediate(function () { | ||
end.call(originalResponse) | ||
}) | ||
setImmediate(function() { | ||
end.call(originalResponse); | ||
}); | ||
} | ||
} | ||
}; | ||
hijackedResponse.__defineGetter__('statusCode', function () { | ||
return originalResponse.statusCode | ||
}) | ||
hijackedResponse.__defineGetter__("statusCode", function() { | ||
return originalResponse.statusCode; | ||
}); | ||
hijackedResponse.__defineSetter__('statusCode', function (statusCode) { | ||
originalResponse.statusCode = statusCode | ||
}) | ||
hijackedResponse.__defineSetter__("statusCode", function(statusCode) { | ||
originalResponse.statusCode = statusCode; | ||
}); | ||
res.writeHead = function (statusCode, statusMessage, headers) { | ||
if (typeof headers === 'undefined' && typeof statusMessage === 'object') { | ||
headers = statusMessage | ||
statusMessage = undefined | ||
res.writeHead = function(statusCode, statusMessage, headers) { | ||
if (typeof headers === "undefined" && typeof statusMessage === "object") { | ||
headers = statusMessage; | ||
statusMessage = undefined; | ||
} | ||
if (statusCode) { | ||
res.statusCode = statusCode | ||
res.statusCode = statusCode; | ||
} | ||
if (headers) { | ||
for (var headerName in headers) { | ||
res.setHeader(headerName, headers[headerName]) | ||
res.setHeader(headerName, headers[headerName]); | ||
} | ||
} | ||
res.writeHead = writeHead | ||
cb(null, hijackedResponse) | ||
} | ||
res.writeHead = writeHead; | ||
cb(null, hijackedResponse); | ||
}; | ||
hijackedResponse.unhijack = function () { | ||
hijacking = false | ||
res.write = write | ||
res.end = end | ||
return originalResponse | ||
} | ||
} | ||
hijackedResponse.unhijack = function() { | ||
hijacking = false; | ||
res.write = write; | ||
res.end = end; | ||
return originalResponse; | ||
}; | ||
}; |
{ | ||
"name": "hijackresponse", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "Hijack HttpResponses", | ||
@@ -8,22 +8,22 @@ "main": "lib/hijackResponse.js", | ||
"bufferedstream": "3.1.1", | ||
"compression": "1.6.1", | ||
"compression": "^1.7.0", | ||
"coveralls": "2.11.4", | ||
"errorhandler": "1.4.2", | ||
"eslint": "^5.15.0", | ||
"eslint-config-pretty-standard": "^2.0.1", | ||
"eslint-plugin-import": "^2.16.0", | ||
"express": "4.13.3", | ||
"http-proxy-middleware": "0.17.4", | ||
"istanbul": "0.3.20", | ||
"lodash": "3.10.1", | ||
"mocha": "2.3.2", | ||
"mocha": "^6.0.2", | ||
"nyc": "^13.3.0", | ||
"passerror": "1.1.0", | ||
"sinon": "1.17.3", | ||
"standard": "5.3.0", | ||
"unexpected": "10.13.0", | ||
"unexpected-express": "8.2.0", | ||
"unexpected-sinon": "10.2.0" | ||
"prettier": "^1.16.4", | ||
"unexpected": "^11.1.1", | ||
"unexpected-express": "^11.1.2" | ||
}, | ||
"scripts": { | ||
"coverage": "istanbul --include-all-sources cover _mocha", | ||
"lint": "standard", | ||
"coverage": "nyc mocha && nyc report --reporter=html", | ||
"coverage:ci": "nyc mocha && nyc report --reporter=lcov", | ||
"lint": "eslint . && prettier --check '**/*.js'", | ||
"test": "mocha", | ||
"travis": "npm run lint && npm run coverage", | ||
"submit-coveralls": "<coverage/lcov.info coveralls" | ||
@@ -38,5 +38,5 @@ }, | ||
"contributors": [ | ||
"Andreas Lind <andreas@one.com>" | ||
"Andreas Lind <andreaslindpetersen@gmail.com>" | ||
], | ||
"license": "ISC" | ||
} |
@@ -11,2 +11,4 @@ # hijackresponse | ||
Require node v6 or later. | ||
This module is the spiritual successor to | ||
@@ -38,28 +40,26 @@ [express-hijackresponse](https://github.com/papandreou/express-hijackresponse) | ||
```js | ||
var express = require('express'); | ||
var hijackResponse = require('hijackresponse'); | ||
var express = require("express"); | ||
var hijackResponse = require("hijackresponse"); | ||
var app = express(); | ||
app.use(function (req, res, next) { | ||
hijackResponse(res, function (err, res) { | ||
if (err) { | ||
res.unhijack(); // Make the original res object work again | ||
return next(err); | ||
} | ||
app.use(function(req, res, next) { | ||
hijackResponse(res, function(err, res) { | ||
if (err) { | ||
res.unhijack(); // Make the original res object work again | ||
return next(err); | ||
} | ||
// Don't hijack HTML responses: | ||
if (/^text\/html(?:;$)/.test(res.getHeader('Content-Type'))) { | ||
return res.unhijack(); | ||
} | ||
// Don't hijack HTML responses: | ||
if (/^text\/html(?:;$)/.test(res.getHeader("Content-Type"))) { | ||
return res.unhijack(); | ||
} | ||
res.setHeader('X-Hijacked', 'yes!'); | ||
res.removeHeader('Content-Length'); | ||
res.setHeader("X-Hijacked", "yes!"); | ||
res.removeHeader("Content-Length"); | ||
res | ||
.pipe(transformStream) | ||
.pipe(res); | ||
}); | ||
// next() must be called explicitly, even when hijacking the response: | ||
next(); | ||
res.pipe(transformStream).pipe(res); | ||
}); | ||
// next() must be called explicitly, even when hijacking the response: | ||
next(); | ||
}); | ||
@@ -66,0 +66,0 @@ ``` |
@@ -1,291 +0,334 @@ | ||
/* global describe, it, beforeEach, afterEach */ | ||
var expect = require('./unexpected-with-plugins') | ||
var passError = require('passerror') | ||
var http = require('http') | ||
var hijackResponse = require('../') | ||
var sinon = require('sinon') | ||
const createTestServer = require("./helpers/test-server"); | ||
const expect = require("unexpected"); | ||
const hijackResponse = require("../lib/hijackResponse"); | ||
const stream = require("stream"); | ||
describe('hijackResponse', function () { | ||
it('should be able to hijack a reponse and rewrite it', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
var chunks = [] | ||
res.on('data', function (chunk) { | ||
chunks.push(chunk) | ||
}) | ||
res.on('end', function () { | ||
var result = Buffer.concat(chunks).toString('utf-8').toUpperCase() | ||
res.write(result, 'utf-8') | ||
res.end() | ||
}) | ||
})) | ||
describe("hijackResponse", () => { | ||
it("should be able to hijack a reponse and rewrite it", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => { | ||
let chunks = []; | ||
res.setHeader('Content-Type', 'text/plain') | ||
res.write('foo') | ||
res.end() | ||
}, 'to yield response', 'FOO') | ||
}) | ||
it('should be able to pipe hijacked res into it self.', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
res.on("data", chunk => chunks.push(chunk)); | ||
res.setHeader('Content-Type', 'text/plain') | ||
res.write('foo') | ||
res.write('bar') | ||
res.end() | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('should be able to hijack an already hijacked response', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
var chunks = [] | ||
res.on('data', function (chunk) { | ||
chunks.push(chunk) | ||
}).on('end', function () { | ||
res.setHeader('X-qux', 'hijacked') | ||
res.write(Buffer.concat(chunks)) | ||
res.end('qux') | ||
}) | ||
})) | ||
res.on("end", () => { | ||
const stringifiedResponse = Buffer.concat(chunks).toString("utf-8"); | ||
res.end(stringifiedResponse.toUpperCase()); | ||
}); | ||
}); | ||
res.setHeader('X-bar', 'hijacked') | ||
res.on('data', function (chunk) { | ||
res.write(chunk) | ||
}).on('end', function () { | ||
res.write('bar') | ||
res.end() | ||
}) | ||
})) | ||
res.setHeader("Content-Type", "text/plain"); | ||
res.end("foo"); | ||
}); | ||
res.setHeader('Content-Type', 'text/plain') | ||
res.write('foo') | ||
res.end() | ||
}, 'to yield response', { | ||
return expect(request(), "when fulfilled", "to satisfy", { body: "FOO" }); | ||
}); | ||
it("should pipe through a transform stream", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => { | ||
const uppercaseStream = new stream.Transform({ | ||
transform(chunk, encoding, callback) { | ||
if (encoding !== "utf-8") { | ||
chunk = Buffer.from(chunk).toString("utf-8"); | ||
} | ||
chunk = chunk.toUpperCase(); | ||
callback(null, chunk); | ||
} | ||
}); | ||
res.pipe(uppercaseStream).pipe(res); | ||
}); | ||
res.setHeader("Content-Type", "text/plain"); | ||
res.write("foo"); | ||
res.end("bar"); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "FOOBAR" | ||
}); | ||
}); | ||
it("should be able to pipe hijacked res into it self.", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.setHeader("Content-Type", "text/plain"); | ||
res.write("foo"); | ||
res.write("bar"); | ||
res.end(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
it("should be able to hijack an already hijacked response", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => { | ||
hijackResponse(res, (err, res) => { | ||
const chunks = []; | ||
res | ||
.on("data", chunk => chunks.push(chunk)) | ||
.on("end", () => { | ||
res.setHeader("X-qux", "hijacked"); | ||
res.write(Buffer.concat(chunks)); | ||
res.end("qux"); | ||
}); | ||
}); | ||
res.setHeader("X-bar", "hijacked"); | ||
res | ||
.on("data", chunk => res.write(chunk)) | ||
.on("end", () => { | ||
res.write("bar"); | ||
res.end(); | ||
}); | ||
}); | ||
res.setHeader("Content-Type", "text/plain"); | ||
res.write("foo"); | ||
res.end(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
headers: { | ||
'X-qux': 'hijacked', | ||
'X-bar': 'hijacked' | ||
"content-type": "text/plain", | ||
"x-bar": "hijacked", | ||
"x-qux": "hijacked" | ||
}, | ||
body: 'foobarqux' | ||
}) | ||
}) | ||
it('should be able to hijack an already hijacked response when piping', function () { | ||
function appendToStream (value) { | ||
var Transform = require('stream').Transform | ||
var appendTo = new Transform({}) | ||
appendTo._transform = function (chunk, encoding, cb) { | ||
this.push(chunk) | ||
cb() | ||
} | ||
appendTo._flush = function (cb) { | ||
this.push(new Buffer(value)) | ||
cb() | ||
} | ||
return appendTo | ||
} | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(appendToStream('qux')).pipe(res) | ||
})) | ||
res.pipe(appendToStream('baz')).pipe(res) | ||
})) | ||
body: "foobarqux" | ||
}); | ||
}); | ||
res.setHeader('Content-Type', 'text/plain') | ||
it("should be able to hijack an already hijacked response when piping", () => { | ||
const appendToStream = value => | ||
new stream.Transform({ | ||
transform(chunk, encoding, cb) { | ||
this.push(chunk); | ||
cb(); | ||
}, | ||
flush(cb) { | ||
this.push(Buffer.from(value)); | ||
cb(); | ||
} | ||
}); | ||
var num = 0 | ||
function tick () { | ||
res.write('foo') | ||
num += 1 | ||
if (num < 5) return setImmediate(tick) | ||
res.end('bar') | ||
} | ||
tick() | ||
}, 'to yield response', 'foofoofoofoofoobarbazqux') | ||
}) | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => { | ||
hijackResponse(res, (err, res) => { | ||
res.pipe(appendToStream("qux")).pipe(res); | ||
}); | ||
res.pipe(appendToStream("baz")).pipe(res); | ||
}); | ||
it('should write the last chunk', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.end('foobar') | ||
})) | ||
res.setHeader("Content-Type", "text/plain"); | ||
res.setHeader('content-type', 'text/plain') | ||
res.writeHead(200) | ||
}, 'to yield response', 'foobar') | ||
}) | ||
describe('res.writeHead should trigger the hijackResponse callback', function () { | ||
it('when called without anything', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.end('foobar') | ||
})) | ||
let num = 0; | ||
const tick = () => { | ||
res.write("foo"); | ||
num += 1; | ||
if (num < 5) return setImmediate(tick); | ||
res.end("bar"); | ||
}; | ||
tick(); | ||
}); | ||
res.setHeader('content-type', 'text/plain') | ||
res.writeHead() | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('when called with only a status code', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.end('foobar') | ||
})) | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foofoofoofoofoobarbazqux" | ||
}); | ||
}); | ||
res.setHeader('content-type', 'text/plain') | ||
res.writeHead(200) | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('when called with status code and headers', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.end('foobar') | ||
})) | ||
it("should write the last chunk", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.end("foobar")); | ||
res.setHeader("content-type", "text/plain"); | ||
res.writeHead(200); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
describe("res.writeHead should trigger the hijackResponse callback", () => { | ||
it("when called without anything", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.end("foobar")); | ||
res.setHeader("content-type", "text/plain"); | ||
res.writeHead(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
it("when called with only a status code", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.end("foobar")); | ||
res.setHeader("content-type", "text/plain"); | ||
res.writeHead(200); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
it("when called with status code and headers", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.end("foobar")); | ||
res.writeHead(200, { | ||
'content-type': 'text/plain' | ||
}) | ||
}, 'to yield response', 'foobar') | ||
}) | ||
}) | ||
describe('res.write', function () { | ||
it('should work when called with a buffer', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
"content-type": "text/plain" | ||
}); | ||
}); | ||
res.setHeader('content-type', 'text/plain') | ||
res.write(new Buffer('foobar', 'utf-8')) | ||
res.end() | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('should work when called with null', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
}); | ||
res.setHeader('content-type', 'text/plain') | ||
res.write(new Buffer('foobar', 'utf-8')) | ||
res.write(null) | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('should work when called with a string', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
describe("res.write", () => { | ||
it("should work when called with a buffer", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.setHeader('content-type', 'text/plain') | ||
res.write('foobar') | ||
res.end() | ||
}, 'to yield response', 'foobar') | ||
}) | ||
it('should work when called with a string and an encoding', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
res.setHeader("content-type", "text/plain"); | ||
res.write(new Buffer("foobar", "utf-8")); | ||
res.end(); | ||
}); | ||
res.setHeader('content-type', 'text/plain') | ||
res.write('foobar', 'utf-8') | ||
res.end() | ||
}, 'to yield response', 'foobar') | ||
}) | ||
}) | ||
describe('res.end', function () { | ||
it('should call res._implicitHeader if it havent been called before', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.pipe(res) | ||
})) | ||
res.end() | ||
}, 'to yield response', 200) | ||
}) | ||
}) | ||
describe('res.unhijack', function () { | ||
it('should allow the original data through if unhijacked', function () { | ||
return expect(function (res, handleError) { | ||
hijackResponse(res, passError(handleError, function (res) { | ||
res.unhijack() | ||
})) | ||
res.setHeader('content-type', 'text/plain') | ||
setTimeout(function () { | ||
res.write('foobar') | ||
res.end() | ||
}, 10) | ||
}, 'to yield response', 'foobar') | ||
}) | ||
}) | ||
describe('against a real server', function () { | ||
var handleRequest | ||
var server | ||
var serverAddress | ||
var serverHostname | ||
var serverUrl | ||
beforeEach(function () { | ||
handleRequest = undefined | ||
server = http.createServer(function (req, res) { | ||
res.sendDate = false | ||
handleRequest(req, res) | ||
}).listen(0) | ||
serverAddress = server.address() | ||
serverHostname = serverAddress.address === '::' ? 'localhost' : serverAddress.address | ||
serverUrl = 'http://' + serverHostname + ':' + serverAddress.port + '/' | ||
}) | ||
afterEach(function () { | ||
server.close() | ||
}) | ||
it('should emit the close event on the hijacked response', function () { | ||
return expect.promise(function (run) { | ||
handleRequest = run(function (req, res) { | ||
hijackResponse(res, run(function (err, res) { | ||
expect(err, 'to be falsy') | ||
res.on('close', run(function () {})) | ||
})) | ||
res.end('yaddayadda') | ||
}) | ||
var request = http.get(serverUrl) | ||
request.end('foo') | ||
setTimeout(function () { | ||
request.abort() | ||
}, 10) | ||
request.on('error', run(function (err) { | ||
expect(err, 'to have message', 'socket hang up') | ||
})) | ||
}) | ||
}) | ||
}) | ||
describe('#destroyHijacked', function () { | ||
it('should prevent hijackedRes from emitting more data', function () { | ||
return expect(function (res, handleError) { | ||
var closeSpy = sinon.spy() | ||
hijackResponse(res, passError(handleError, function (res) { | ||
setTimeout(function () { // Wait for .write('foo') to trigger writeHead and push | ||
sinon.spy(res, 'emit') | ||
res.destroyHijacked() | ||
setTimeout(function () { | ||
expect(res._readableState.buffer, 'to equal', []) | ||
expect(res.emit, 'to have calls satisfying', []) | ||
expect(closeSpy, 'to have calls satisfying', function () { | ||
closeSpy() | ||
}) | ||
res.end() | ||
}, 1) | ||
}, 1) | ||
})) | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
res.on('close', closeSpy) | ||
res.write('foo') | ||
setTimeout(function () { | ||
res.write('bar') | ||
}, 0) | ||
}, 'to yield response', { | ||
it("should work when called with null", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.setHeader("content-type", "text/plain"); | ||
res.write(Buffer.from("foobar")); | ||
res.write(null); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
it("should work when called with a string", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.setHeader("content-type", "text/plain"); | ||
res.write("foobar"); | ||
res.end(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
it("should work when called with a string and an encoding", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.setHeader("content-type", "text/plain"); | ||
res.write("foobar", "utf-8"); | ||
res.end(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
}); | ||
describe("res.end", () => { | ||
it("should call res._implicitHeader if it havent been called before", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.pipe(res)); | ||
res.end(); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
statusCode: 200 | ||
}); | ||
}); | ||
}); | ||
describe("res.unhijack", () => { | ||
it("should allow the original data through if unhijacked", () => { | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => res.unhijack()); | ||
res.setHeader("content-type", "text/plain"); | ||
setTimeout(() => res.end("foobar"), 10); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
body: "foobar" | ||
}); | ||
}); | ||
}); | ||
describe("#destroyHijacked", function() { | ||
it("should prevent hijackedRes from emitting more data", function() { | ||
let closeCalledCount = 0; | ||
const closeSpy = () => { | ||
closeCalledCount += 1; | ||
}; | ||
const emits = []; | ||
const spyEmit = res => { | ||
const origEmit = res.emit; | ||
res.emit = (...args) => { | ||
emits.push(args); | ||
origEmit.apply(res, args); | ||
}; | ||
return () => { | ||
res.emit = origEmit; | ||
}; | ||
}; | ||
const request = createTestServer((req, res) => { | ||
hijackResponse(res, (err, res) => { | ||
// Wait for .write('foo') to trigger writeHead and push | ||
const restoreEmit = spyEmit(res); | ||
setTimeout(() => { | ||
res.destroyHijacked(); | ||
setTimeout(() => { | ||
restoreEmit(); | ||
res.end(); | ||
}, 1); | ||
}, 1); | ||
}); | ||
res.on("close", closeSpy); | ||
res.write("foo"); | ||
setTimeout(() => res.write("bar"), 0); | ||
}); | ||
return expect(request(), "when fulfilled", "to satisfy", { | ||
statusCode: 200, | ||
unchunkedBody: expect.it('to equal', new Buffer([])).or('to be undefined') | ||
}) | ||
}) | ||
}) | ||
}) | ||
rawBody: Buffer.concat([]) | ||
}).then(() => { | ||
return expect({ closeCalledCount, emits }, "to satisfy", { | ||
closeCalledCount: 1, | ||
emits: [] | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
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
Network access
Supply chain riskThis module accesses the network.
Found 2 instances 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
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
2030437
16
792
6