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

messy

Package Overview
Dependencies
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

messy - npm Package Compare versions

Comparing version 0.4.1 to 0.5.0

16

lib/Headers.js
var foldHeaderLine = require('./foldHeaderLine'),
formatHeaderName = require('./formatHeaderName');
function Headers(objectOrString) {
function Headers(obj) {
this.valuesByName = {};
this.populate(objectOrString);
this.populate(obj);
}
Headers.prototype.populate = function (objectOrString) {
if (typeof objectOrString === 'string') {
this.populateFromString(objectOrString);
} else if (objectOrString && typeof objectOrString === 'object') {
this.setAll(objectOrString);
Headers.prototype.populate = function (obj) {
if (typeof obj === 'string') {
this.populateFromString(obj);
} else if (obj && typeof obj === 'object') {
this.populateFromObject(obj);
}

@@ -97,3 +97,3 @@ };

Headers.prototype.setAll = function (valuesByName) {
Headers.prototype.populateFromObject = function (valuesByName) {
Object.keys(valuesByName).forEach(function (headerName) {

@@ -100,0 +100,0 @@ var value = valuesByName[headerName],

var Message = require('./Message'),
util = require('util');
function HttpRequest(stringOrObjectOrBuffer) {
Message.call(this, stringOrObjectOrBuffer);
if (stringOrObjectOrBuffer && typeof stringOrObjectOrBuffer === 'object' && !Buffer.isBuffer(stringOrObjectOrBuffer)) {
if (stringOrObjectOrBuffer.requestLine) {
this.populateRequestLineFromString(stringOrObjectOrBuffer.requestLine);
}
if (stringOrObjectOrBuffer.method) {
this.method = stringOrObjectOrBuffer.method.toUpperCase();
}
if (stringOrObjectOrBuffer.url) {
this.url = stringOrObjectOrBuffer.url;
}
if (stringOrObjectOrBuffer.protocol) {
this.protocol = String(stringOrObjectOrBuffer.protocol).toUpperCase();
}
}
function HttpRequest(obj) {
Message.call(this, obj);
}
HttpRequest.propertyNames = ['requestLine', 'method', 'url', 'path', 'search', 'query', 'protocol', 'protocolName', 'protocolVersion'];
util.inherits(HttpRequest, Message);
HttpRequest.prototype.populate = function (obj) {
Message.prototype.populate.call(this, obj);
if (obj && typeof obj === 'object' && !Buffer.isBuffer(obj)) {
this.populateFromObject(obj);
}
};
HttpRequest.prototype.populateFromObject = function (obj) {
Message.prototype.populateFromObject.call(this, obj);
HttpRequest.propertyNames.forEach(function (propertyName) {
if (typeof obj[propertyName] !== 'undefined') {
this[propertyName] = obj[propertyName];
}
}, this);
};
HttpRequest.prototype.populateProtocolFromString = function (protocol) {
var protocolFragments = protocol.split('/');
if (protocolFragments.length === 2) {
this.protocolName = protocolFragments[0];
this.protocolVersion = protocolFragments[1];
} else {
throw new Error('Could not parse protocol: ' + protocol);
}
};
HttpRequest.prototype.populateRequestLineFromString = function (requestLine) {

@@ -29,3 +43,3 @@ var requestLineFragments = requestLine.split(/\s+/);

this.url = requestLineFragments[1];
this.protocol = requestLineFragments[2];
this.populateProtocolFromString(requestLineFragments[2]);
} else {

@@ -36,2 +50,48 @@ throw new Error('Could not parse request line: ' + requestLine);

HttpRequest.prototype.populateUrlFromString = function (url) {
var matchUrl = url.match(/^([^?]*)(\?.*)?$/);
this.path = matchUrl[1] || '';
this.search = matchUrl[2] || '';
};
Object.defineProperty(HttpRequest.prototype, 'requestLine', {
enumerable: true,
get: function () {
return String(this.method).toUpperCase() + ' ' + this.url + ' ' + this.protocol;
},
set: function (requestLine) {
this.populateRequestLineFromString(requestLine);
}
});
Object.defineProperty(HttpRequest.prototype, 'protocol', {
enumerable: true,
get: function () {
return String(this.protocolName).toUpperCase() + '/' + this.protocolVersion;
},
set: function (protocol) {
this.populateProtocolFromString(protocol);
}
});
Object.defineProperty(HttpRequest.prototype, 'url', {
enumerable: true,
get: function () {
return (this.path || '') + (this.search || '');
},
set: function (url) {
this.populateUrlFromString(url);
}
});
Object.defineProperty(HttpRequest.prototype, 'query', {
enumerable: true,
get: function () {
return (this.search || '').replace(/^\?/, '');
},
set: function (query) {
this.url = this.url.replace(/(?:\?.*)?$/, '?' + query);
}
});
HttpRequest.prototype.populateFromString = function (str) {

@@ -50,3 +110,3 @@ var matchRequestLine = str.match(/^([^\r\n]*)(\r\n?|\n\r?|$)/);

return (
this.method + ' ' + this.url + ' ' + this.protocol + '\r\n' +
this.requestLine + '\r\n' +
Message.prototype.toString.call(this, maxLineLength)

@@ -60,4 +120,6 @@ );

this.method === other.method &&
this.url === other.url &&
this.protocol === other.protocol &&
(this.path || '') === (other.path || '') &&
(this.search || '') === (other.search || '') &&
this.protocolName === other.protocolName &&
this.protocolVersion === other.protocolVersion &&
Message.prototype.equals.call(this, other)

@@ -67,2 +129,16 @@ );

// Exploratory work wrt. https://github.com/sunesimonsen/unexpected/issues/40
// FIXME: Makes no sense that you have to specify every property,
// including the "aggregated ones", when mustBeExhaustive is true
HttpRequest.prototype.satisfies = function (spec, mustBeExhaustive) {
if (!Message.prototype.satisfies.call(this, spec, mustBeExhaustive)) {
return false;
}
return HttpRequest.propertyNames.every(function (propertyName) {
return (propertyName in spec) ?
this[propertyName] === spec[propertyName] :
!mustBeExhaustive || typeof this[propertyName] === 'undefined';
}, this);
};
module.exports = HttpRequest;
var Message = require('./Message'),
util = require('util');
function HttpResponse(stringOrObjectOrBuffer) {
Message.call(this, stringOrObjectOrBuffer);
if (stringOrObjectOrBuffer && typeof stringOrObjectOrBuffer === 'object' && !Buffer.isBuffer(stringOrObjectOrBuffer)) {
if (stringOrObjectOrBuffer.statusLine) {
this.populateStatusLineFromString(stringOrObjectOrBuffer.statusLine);
}
if (stringOrObjectOrBuffer.protocol) {
this.protocol = String(stringOrObjectOrBuffer.protocol).toUpperCase();
}
if ('statusCode' in stringOrObjectOrBuffer) {
if (typeof stringOrObjectOrBuffer === 'number') {
this.statusCode = stringOrObjectOrBuffer.statusCode;
} else {
this.statusCode = parseInt(stringOrObjectOrBuffer.statusCode, 10);
}
}
if ('statusMessage' in stringOrObjectOrBuffer) {
this.statusMessage = String(stringOrObjectOrBuffer.statusMessage);
}
}
function HttpResponse(obj) {
Message.call(this, obj);
}
HttpResponse.propertyNames = ['statusLine', 'protocol', 'protocolName', 'protocolVersion', 'statusCode', 'statusMessage'];
util.inherits(HttpResponse, Message);
HttpResponse.prototype.populate = function (obj) {
Message.prototype.populate.call(this, obj);
if (obj && typeof obj === 'object' && !Buffer.isBuffer(obj)) {
this.populateFromObject(obj);
}
};
HttpResponse.prototype.populateFromObject = function (obj) {
Message.prototype.populateFromObject.call(this, obj);
HttpResponse.propertyNames.forEach(function (propertyName) {
if (typeof obj[propertyName] !== 'undefined') {
this[propertyName] = obj[propertyName];
}
}, this);
};
HttpResponse.prototype.populateProtocolFromString = function (protocol) {
var protocolFragments = protocol.split('/');
if (protocolFragments.length === 2) {
this.protocolName = protocolFragments[0];
this.protocolVersion = protocolFragments[1];
} else {
throw new Error('Could not parse protocol: ' + protocol);
}
};
HttpResponse.prototype.populateStatusLineFromString = function (statusLine) {
var matchStatusLine = statusLine.match(/^(\S+) (\d+) (.+)$/);
if (matchStatusLine) {
this.protocol = matchStatusLine[1];
this.populateProtocolFromString(matchStatusLine[1]);
this.statusCode = parseInt(matchStatusLine[2], 10);

@@ -39,2 +49,22 @@ this.statusMessage = matchStatusLine[3];

Object.defineProperty(HttpResponse.prototype, 'protocol', {
enumerable: true,
get: function () {
return String(this.protocolName).toUpperCase() + '/' + this.protocolVersion;
},
set: function (protocol) {
this.populateProtocolFromString(protocol);
}
});
Object.defineProperty(HttpResponse.prototype, 'statusLine', {
enumerable: true,
get: function () {
return this.protocol + ' ' + this.statusCode + ' ' + this.statusMessage;
},
set: function (statusLine) {
this.populateStatusLineFromString(statusLine);
}
});
HttpResponse.prototype.populateFromString = function (str) {

@@ -53,3 +83,3 @@ var matchStatusLine = str.match(/^([^\r\n]*)(\r\n?|\n\r?|$)/);

return (
this.protocol + ' ' + this.statusCode + ' ' + this.statusMessage + '\r\n' +
this.statusLine + '\r\n' +
Message.prototype.toString.call(this, maxLineLength)

@@ -62,3 +92,4 @@ );

other instanceof HttpResponse &&
this.protocol === other.protocol &&
this.protocolName === other.protocolName &&
this.protocolVersion === other.protocolVersion &&
this.statusCode === other.statusCode &&

@@ -70,2 +101,16 @@ this.statusMessage === other.statusMessage &&

// Exploratory work wrt. https://github.com/sunesimonsen/unexpected/issues/40
// FIXME: Makes no sense that you have to specify every property,
// including the "aggregated ones", when mustBeExhaustive is true
HttpResponse.prototype.satisfies = function (spec, mustBeExhaustive) {
if (!Message.prototype.satisfies.call(this, spec, mustBeExhaustive)) {
return false;
}
return HttpResponse.propertyNames.every(function (propertyName) {
return (propertyName in spec) ?
this[propertyName] === spec[propertyName] :
!mustBeExhaustive || typeof this[propertyName] === 'undefined';
}, this);
};
module.exports = HttpResponse;
/*global unescape*/
var Headers = require('./Headers');
function Message(stringOrObjectOrBuffer) {
function Message(obj) {
this.headers = new Headers();
if (Buffer.isBuffer(stringOrObjectOrBuffer)) {
this.populateFromBuffer(stringOrObjectOrBuffer);
} else if (typeof stringOrObjectOrBuffer === 'string') {
this.populateFromString(stringOrObjectOrBuffer);
} else if (stringOrObjectOrBuffer && typeof stringOrObjectOrBuffer === 'object') {
if (typeof stringOrObjectOrBuffer.headers !== 'undefined') {
this.headers.populate(stringOrObjectOrBuffer.headers);
}
if (typeof stringOrObjectOrBuffer.body !== 'undefined') {
this.body = stringOrObjectOrBuffer.body;
}
}
this.populate(obj);
}
Message.prototype.populate = function (obj) {
if (Buffer.isBuffer(obj)) {
this.populateFromBuffer(obj);
} else if (typeof obj === 'string') {
this.populateFromString(obj);
} else if (obj && typeof obj === 'object') {
this.populateFromObject(obj);
}
};
Message.prototype.populateFromObject = function (obj) {
if (typeof obj.headers !== 'undefined') {
this.headers.populate(obj.headers);
}
if (typeof obj.body !== 'undefined') {
this.body = obj.body;
}
};
Message.prototype.populateFromBuffer = function (buffer) {

@@ -48,10 +56,2 @@ // Hack: Interpret non-ASCII in headers as iso-8859-1:

// FIXME: Doesn't compare bodies yet
Message.prototype.equals = function (other) {
if (!this.headers.equals(other.headers)) {
return false;
}
return true;
};
function buffersEqual(a, b) {

@@ -75,4 +75,2 @@ if (a === b) {

function canonicalizeObject(obj, stack) {

@@ -105,2 +103,23 @@ stack = stack || [];

Message.prototype.toString = function (maxLineLength) {
if (typeof maxLineLength === 'undefined') {
maxLineLength = 72;
}
var result = this.headers.toString(maxLineLength) || '\r\n';
if (typeof this.body !== 'undefined') {
result += '\r\n' + this.body;
}
return result;
};
Message.prototype.equals = function (other) {
if (!this.headers.equals(other.headers)) {
return false;
}
return (
this.body === other.body ||
(Buffer.isBuffer(this.body) && Buffer.isBuffer(other.body) && buffersEqual(this.body, other.body))
);
};
// Exploratory work wrt. https://github.com/sunesimonsen/unexpected/issues/40

@@ -111,3 +130,7 @@ Message.prototype.satisfies = function (spec, mustBeExhaustive) {

}
if ('headers' in spec && !this.headers.satisfy(spec.headers)) {
if ('headers' in spec) {
if (!this.headers.satisfy(spec.headers, mustBeExhaustive)) {
return false;
}
} else if (mustBeExhaustive && this.headers.getNames().length > 0) {
return false;

@@ -128,7 +151,11 @@ }

}
} else if (typeof spec.body === 'undefined') {
if (typeof this.body !== 'undefined') {
return false;
}
} else {
throw new Error('Unsupported comparison between different types of bodies');
}
if (typeof this.body === 'undefined') {
}
} else if (mustBeExhaustive && typeof this.body !== 'undefined') {
return false;
}

@@ -138,13 +165,2 @@ return true;

Message.prototype.toString = function (maxLineLength) {
if (typeof maxLineLength === 'undefined') {
maxLineLength = 72;
}
var result = this.headers.toString(maxLineLength) || '\r\n';
if (typeof this.body !== 'undefined') {
result += '\r\n' + this.body;
}
return result;
};
module.exports = Message;
{
"name": "messy",
"version": "0.4.1",
"version": "0.5.0",
"description": "Object model for HTTP and RFC822 messages",

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

@@ -35,8 +35,12 @@ /*global describe, it*/

it('should accept the individual request line fields as options to the constructor and normalize them', function () {
it('should make the request line available as a getter', function () {
expect(new HttpRequest({
method: 'get',
method: 'GET',
url: '/foo',
protocol: 'http/1.1'
}), 'to have properties', {
protocol: 'HTTP/1.1'
}).requestLine, 'to equal', 'GET /foo HTTP/1.1');
});
it('should allow updating the request line via a setter', function () {
var httpRequest = new HttpRequest({
method: 'GET',

@@ -46,4 +50,43 @@ url: '/foo',

});
httpRequest.requestLine = 'PUT /bar HTTP/1.0';
expect(httpRequest, 'to have properties', {
method: 'PUT',
url: '/bar',
protocol: 'HTTP/1.0'
});
});
it('should make the protocol version available as a getter', function () {
expect(new HttpRequest('GET /foo HTTP/1.1').protocolVersion, 'to equal', '1.1');
});
it('should make the protocol name available as a getter', function () {
expect(new HttpRequest('GET /foo HTTP/1.1').protocolName, 'to equal', 'HTTP');
});
it('should make the components of the request url available as individual getters', function () {
expect(new HttpRequest('GET /foo?foo=bar HTTP/1.1'), 'to have properties', {
path: '/foo',
search: '?foo=bar',
query: 'foo=bar'
});
});
it('should make path, query, and search available as individual setters', function () {
var httpRequest = new HttpRequest('GET /foo?foo=bar HTTP/1.1');
httpRequest.search = '?blabla';
httpRequest.path = '/bla';
expect(httpRequest.url, 'to equal', '/bla?blabla');
httpRequest.query = 'foobar';
expect(httpRequest.url, 'to equal', '/bla?foobar');
});
it('should accept the individual request line fields as options to the constructor', function () {
expect(new HttpRequest({
method: 'get',
url: '/foo',
protocol: 'http/1.1'
}).requestLine, 'to equal', 'GET /foo HTTP/1.1');
});
it('should consider an identical instance equal', function () {

@@ -84,2 +127,78 @@ var httpRequest1 = new HttpRequest('GET /foo HTTP/1.1\r\nHost: foo.com\r\n\r\nblah'),

});
describe('#satisfies', function () {
it('should match on properties defined by Message', function () {
expect(new HttpRequest('GET /foo HTTP/1.1\r\nContent-Type: text/html').satisfies({
headers: {
'Content-Type': 'text/html'
}
}), 'to be true');
});
it('should fail when matching on properties defined by Message', function () {
expect(new HttpRequest('GET /foo HTTP/1.1\r\nContent-Type: text/html').satisfies({
headers: {
'Content-Type': 'text/plain'
}
}), 'to be false');
});
it('should match on properties', function () {
expect(new HttpRequest('GET /foo HTTP/1.1\r\nContent-Type: text/html').satisfies({
method: 'GET',
url: '/foo',
protocolVersion: '1.1'
}), 'to be true');
});
it('should match exhaustively on properties', function () {
expect(new HttpRequest('GET /foo?hey HTTP/1.1\r\nContent-Type: text/html').satisfies({
requestLine: 'GET /foo?hey HTTP/1.1',
method: 'GET',
url: '/foo?hey',
path: '/foo',
search: '?hey',
query: 'hey',
protocol: 'HTTP/1.1',
protocolName: 'HTTP',
protocolVersion: '1.1',
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be true');
});
it('should fail to match exhaustively on properties when a property is omitted', function () {
expect(new HttpRequest('GET /foo?hey HTTP/1.1\r\nContent-Type: text/html').satisfies({
requestLine: 'GET /foo?hey HTTP/1.1',
url: '/foo?hey',
path: '/foo',
search: '?hey',
query: 'hey',
protocol: 'HTTP/1.1',
protocolName: 'HTTP',
protocolVersion: '1.1',
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be false');
});
it('should fail to match exhaustively on properties when a property defined by Message is omitted', function () {
expect(new HttpRequest('GET /foo?hey HTTP/1.1\r\nContent-Type: text/html\r\nargh').satisfies({
requestLine: 'GET /foo?hey HTTP/1.1',
method: 'GET',
url: '/foo?hey',
path: '/foo',
search: '?hey',
query: 'hey',
protocol: 'HTTP/1.1',
protocolName: 'HTTP',
protocolVersion: '1.1',
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be false');
});
});
});

@@ -43,3 +43,3 @@ /*global describe, it*/

it('should accept the individual status line fields as options to the constructor', function () {
it('should make the status line available as a getter', function () {
expect(new HttpResponse({

@@ -49,3 +49,7 @@ protocol: 'HTTP/1.1',

statusMessage: 'OK'
}), 'to have properties', {
}).statusLine, 'to equal', 'HTTP/1.1 200 OK');
});
it('should allow updating the status line via a setter', function () {
var httpResponse = new HttpResponse({
protocol: 'HTTP/1.1',

@@ -55,11 +59,27 @@ statusCode: 200,

});
httpResponse.statusLine = 'HTTP/1.0 400 Bad Request';
expect(httpResponse, 'to have properties', {
protocol: 'HTTP/1.0',
statusCode: 400,
statusMessage: 'Bad Request'
});
});
it('should normalize the protocol and the status code when given as individual options to the constructor', function () {
it('should make the protocol version available as a getter', function () {
expect(new HttpResponse('HTTP/1.1 200 OK').protocolVersion, 'to equal', '1.1');
});
it('should make the protocol name available as a getter', function () {
expect(new HttpResponse('HTTP/1.0 200 OK').protocolName, 'to equal', 'HTTP');
});
it('should accept the individual status line properties as options to the constructor', function () {
expect(new HttpResponse({
protocol: 'http/1.1',
statusCode: '200'
protocol: 'HTTP/1.1',
statusCode: 200,
statusMessage: 'OK'
}), 'to have properties', {
protocol: 'HTTP/1.1',
statusCode: 200
statusCode: 200,
statusMessage: 'OK'
});

@@ -103,2 +123,70 @@ });

});
describe('#satisfies', function () {
it('should match on properties defined by Message', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html').satisfies({
headers: {
'Content-Type': 'text/html'
}
}), 'to be true');
});
it('should fail when matching on properties defined by Message', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html').satisfies({
headers: {
'Content-Type': 'text/plain'
}
}), 'to be false');
});
it('should match on properties', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html').satisfies({
statusCode: 200,
protocolVersion: '1.1'
}), 'to be true');
});
it('should match exhaustively on properties', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html').satisfies({
statusLine: 'HTTP/1.1 200 OK',
statusCode: 200,
statusMessage: 'OK',
protocol: 'HTTP/1.1',
protocolName: 'HTTP',
protocolVersion: '1.1',
body: undefined,
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be true');
});
it('should fail to match exhaustively on properties when a property is omitted', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html').satisfies({
statusLine: 'HTTP/1.1 200 OK',
statusCode: 200,
statusMessage: 'OK',
protocol: 'HTTP/1.1',
protocolVersion: '1.1',
body: undefined,
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be false');
});
it('should fail to match exhaustively on properties when a property defined by Message is omitted', function () {
expect(new HttpResponse('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nargh').satisfies({
statusLine: 'HTTP/1.1 200 OK',
statusCode: 200,
statusMessage: 'OK',
protocol: 'HTTP/1.1',
protocolName: 'HTTP',
protocolVersion: '1.1',
headers: {
'Content-Type': 'text/html'
}
}, true), 'to be false');
});
});
});
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