Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

shot

Package Overview
Dependencies
Maintainers
3
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shot - npm Package Compare versions

Comparing version 3.0.0 to 3.0.1

lib/request.js

299

lib/index.js

@@ -5,286 +5,11 @@ 'use strict';

const Http = require('http');
const Stream = require('stream');
const Util = require('util');
const Url = require('url');
const Hoek = require('hoek');
const Request = require('./request');
const Response = require('./response');
// Declare internals
const internals = {};
internals.Request = function (options) {
Stream.Readable.call(this);
// options: method, url, payload, headers, remoteAddress
let url = options.url;
if (typeof url === 'object') {
url = Url.format(url);
}
const uri = Url.parse(url);
this.url = uri.path;
this.httpVersion = '1.1';
this.method = options.method.toUpperCase();
this.headers = {};
const headers = options.headers || {};
const fields = Object.keys(headers);
fields.forEach((field) => {
this.headers[field.toLowerCase()] = headers[field];
});
this.headers['user-agent'] = this.headers['user-agent'] || 'shot';
this.headers.host = this.headers.host || uri.host || options.authority || 'localhost';
this.connection = {
remoteAddress: options.remoteAddress || '127.0.0.1'
};
// Use _shot namespace to avoid collision with Node
let payload = options.payload || null;
if (payload &&
typeof payload !== 'string' &&
!Buffer.isBuffer(payload)) {
payload = JSON.stringify(payload);
this.headers['content-type'] = this.headers['content-type'] || 'application/json';
}
// Set the content-length for the corresponding payload if none set
if (payload &&
!this.headers.hasOwnProperty('content-length')) {
this.headers['content-length'] = (Buffer.isBuffer(payload) ? payload.length : Buffer.byteLength(payload)).toString();
}
this._shot = {
payload: payload,
isDone: false,
simulate: options.simulate || {}
};
return this;
};
Util.inherits(internals.Request, Stream.Readable);
internals.Request.prototype._read = function (size) {
setImmediate(() => {
if (this._shot.isDone) {
if (this._shot.simulate.end !== false) { // 'end' defaults to true
this.push(null);
}
return;
}
this._shot.isDone = true;
if (this._shot.payload) {
if (this._shot.simulate.split) {
this.push(this._shot.payload.slice(0, 1));
this.push(this._shot.payload.slice(1));
}
else {
this.push(this._shot.payload);
}
}
if (this._shot.simulate.error) {
this.emit('error', new Error('Simulated'));
}
if (this._shot.simulate.close) {
this.emit('close');
}
if (this._shot.simulate.end !== false) { // 'end' defaults to true
this.push(null);
}
});
};
internals.Request.prototype.destroy = function () {
};
internals.Response = function (req, onEnd) {
Http.ServerResponse.call(this, { method: req.method, httpVersionMajor: 1, httpVersionMinor: 1 });
this.once('finish', internals.finish(this, req, onEnd));
return this;
};
Util.inherits(internals.Response, Http.ServerResponse);
internals.Response.prototype.writeHead = function () {
const headers = ((arguments.length === 2 && typeof arguments[1] === 'object') ? arguments[1] : (arguments.length === 3 ? arguments[2] : {}));
const result = Http.ServerResponse.prototype.writeHead.apply(this, arguments);
this._headers = this._headers || {};
const keys = Object.keys(headers);
for (let i = 0; i < keys.length; ++i) {
this._headers[keys[i]] = headers[keys[i]];
}
// Add raw headers
['Date', 'Connection', 'Transfer-Encoding'].forEach((name) => {
const regex = new RegExp('\\r\\n' + name + ': ([^\\r]*)\\r\\n');
const field = this._header.match(regex);
if (field) {
this._headers[name.toLowerCase()] = field[1];
}
});
return result;
};
internals.Response.prototype.write = function (data, encoding) {
Http.ServerResponse.prototype.write.call(this, data, encoding);
return true; // Write always returns false when disconnected
};
internals.Response.prototype.end = function (data, encoding) {
Http.ServerResponse.prototype.end.call(this, data, encoding);
this.emit('finish'); // Will not be emitted when disconnected
};
internals.Response.prototype.destroy = function () {
};
internals.finish = function (response, req, onEnd) {
return function () {
// Prepare response object
const res = {
raw: {
req: req,
res: response
},
headers: response._headers,
statusCode: response.statusCode,
trailers: {}
};
// When done, call callback
process.nextTick(() => {
onEnd(res);
});
// Read payload
const raw = [];
let rawLength = 0;
for (let i = 0; i < response.output.length; ++i) {
const chunk = (response.output[i] instanceof Buffer ? response.output[i] : new Buffer(response.output[i], response.outputEncodings[i]));
raw.push(chunk);
rawLength = rawLength + chunk.length;
}
const rawBuffer = Buffer.concat(raw, rawLength);
// Parse payload
res.payload = '';
const CRLF = '\r\n';
const sep = new Buffer(CRLF + CRLF);
const parts = internals.splitBufferInTwo(rawBuffer, sep);
const payloadBuffer = parts[1];
if (!res.headers['transfer-encoding']) {
res.rawPayload = payloadBuffer;
res.payload = payloadBuffer.toString();
return;
}
const CRLFBuffer = new Buffer(CRLF);
let rest = payloadBuffer;
let payloadBytes = [];
let size;
do {
const payloadParts = internals.splitBufferInTwo(rest, CRLFBuffer);
const next = payloadParts[1];
size = parseInt(payloadParts[0].toString(), 16);
if (size === 0) {
rest = next;
}
else {
const nextData = next.slice(0, size);
payloadBytes = payloadBytes.concat(Array.prototype.slice.call(nextData, 0));
rest = next.slice(size + 2);
}
}
while (size);
res.rawPayload = new Buffer(payloadBytes);
res.payload = res.rawPayload.toString('utf8');
// Parse trailers
const trailerLines = rest.toString().split(CRLF);
trailerLines.forEach((line) => {
const trailerParts = line.split(':');
if (trailerParts.length === 2) {
res.trailers[trailerParts[0].trim().toLowerCase()] = trailerParts[1].trim();
}
});
};
};
internals.splitBufferInTwo = function (buffer, seperator) {
for (let i = 0; i < buffer.length - seperator.length; ++i) {
if (internals.bufferEqual(buffer.slice(i, i + seperator.length), seperator)) {
const part1 = buffer.slice(0, i);
const part2 = buffer.slice(i + seperator.length);
return [part1, part2];
}
}
return [buffer, new Buffer(0)];
};
exports.inject = function (dispatchFunc, options, callback) {
options = (typeof options === 'string' ? { url: options } : options);
const settings = Hoek.applyToDefaults({ method: 'GET' }, options);
const req = new internals.Request(settings);
const res = new internals.Response(req, callback);
dispatchFunc(req, res);
const req = new Request(options);
const res = new Response(req, callback);
return dispatchFunc(req, res);
};

@@ -295,15 +20,3 @@

return (obj instanceof internals.Request || obj instanceof internals.Response);
return (obj instanceof Request || obj instanceof Response);
};
internals.bufferEqual = function (a, b) {
for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
};
{
"name": "shot",
"description": "Injects a fake HTTP request/response into a node HTTP server",
"version": "3.0.0",
"version": "3.0.1",
"repository": "git://github.com/hapijs/shot",

@@ -16,5 +16,2 @@ "main": "lib/index.js",

},
"dependencies": {
"hoek": "3.x.x"
},
"devDependencies": {

@@ -21,0 +18,0 @@ "code": "2.x.x",

@@ -138,3 +138,3 @@ 'use strict';

expect(res.payload).to.equal('localhost');
expect(res.payload).to.equal('localhost:80');
done();

@@ -174,2 +174,32 @@ });

it('includes default http port in host header', (done) => {
const dispatch = function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(req.headers.host);
};
Shot.inject(dispatch, 'http://example.com', (res) => {
expect(res.payload).to.equal('example.com:80');
done();
});
});
it('includes default https port in host header', (done) => {
const dispatch = function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(req.headers.host);
};
Shot.inject(dispatch, 'https://example.com', (res) => {
expect(res.payload).to.equal('example.com:443');
done();
});
});
it('optionally accepts an object as url', (done) => {

@@ -176,0 +206,0 @@

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