Comparing version 2.1.0 to 2.2.0
@@ -105,2 +105,3 @@ var ICAPServer = require('../').ICAPServer; | ||
icapRes.writeHeaders(true); | ||
// only one calling at once. | ||
icapRes.send(errorPage); | ||
@@ -110,2 +111,4 @@ } else { | ||
} | ||
// WARNING: don't forget to write.end() after .send() | ||
// or your data will not send.:( | ||
icapRes.end(); | ||
@@ -112,0 +115,0 @@ }; |
@@ -55,19 +55,10 @@ var ICAPServer = require('../').ICAPServer; | ||
var hasBody = icapReq.hasBody(); | ||
if (hasbody) { | ||
if (hasbody && !icapReq.ieof) { | ||
icapRes.continuePreview(); | ||
} | ||
icapRes.writeHeaders(hasBody); | ||
// .pipe() or .end() must be called. | ||
icapReq.pipe(icapRes); | ||
}; | ||
// filter method | ||
var filterHtml = function(data) { | ||
var str = data.toString(); | ||
// parse dom from str, modify, convert back to string | ||
// pseudocode: | ||
// var dom = parseHtml(str); | ||
// dom.modify(); | ||
// str = dom.toString(); | ||
return str; | ||
} | ||
@@ -91,4 +82,6 @@ // filter html responses | ||
// `filter` function should be a synchronous, but you can use streams now | ||
// configure a filter that will run only after the full response data is received | ||
icapRes.setFilter(true, function(buffer) { | ||
// buffer are always Buffer instance | ||
var str = buffer.toString('utf8'); | ||
@@ -107,4 +100,4 @@ | ||
// the only immediate action is to request the full response body | ||
icapReq.pipe(icapRes); | ||
if (icapReq.hasPreviewBody() && !icapReq.ieof) { | ||
icapReq.pipe(icapRes); // or may be icapReq.pipe(zlib.createUnzip().pipe(icapRes)); | ||
if (icapReq.hasBody() && !icapReq.ieof) { | ||
icapRes.continuePreview(); | ||
@@ -111,0 +104,0 @@ } |
{ | ||
"name": "nodecap2", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "ICAP server framework for node.js - create custom HTTP proxy filters for Squid, etc.", | ||
@@ -11,14 +11,14 @@ "main": "index.js", | ||
"dependencies": { | ||
"eventemitter2": "^0.4.14", | ||
"lodash": "^4.3.0", | ||
"winston": "^2.1.1" | ||
"eventemitter3": "^1.2.0", | ||
"winston": "^2.2.0" | ||
}, | ||
"optionalDependencies": { | ||
"mmmagic": "~0.3.6" | ||
"mmmagic": "^0.4.0" | ||
}, | ||
"devDependencies": { | ||
"tap": "~0.4.8" | ||
"tap": "^6.3.2" | ||
}, | ||
"scripts": { | ||
"test": "tap ./test" | ||
"tap": "tap", | ||
"test": "tap ./test/*_spec.js" | ||
}, | ||
@@ -25,0 +25,0 @@ "repository": { |
@@ -10,2 +10,5 @@ nodecap2 | ||
**WARN** : version 2.2.0 has a bit different behaviour as previous version, so check github repo and your server before upgrading. It's last version that may work with node v0.10. | ||
## Use Case | ||
@@ -68,3 +71,3 @@ [Squid](http://www.squid-cache.org/) and other HTTP proxy servers typically provide only basic levels of filtering. **nodecap** implements the ICAP protocol, allowing for dynamic, per-request filtering and modification of requests and responses. | ||
**nodecap** presents an expressjs-style API where middleware can be declared and matched to requests. Instead of request URI/method combinations, the unit of matching is domains through the `DomainList` class, which implements an efficient matcher for squid3 whitelist/blacklist syntax. Middlware is attached to handle requests to / responses from lists of domains: | ||
**nodecap** presents an expressjs-style API where middleware can be declared and matched to requests. Instead of request URI/method combinations, the unit of matching is domains through the `DomainList` class, which implements an efficient matcher for squid3 whitelist/blacklist syntax. Middleware is attached to handle requests to / responses from lists of domains: | ||
@@ -71,0 +74,0 @@ ### `server.request(domainList, next)` |
@@ -58,9 +58,14 @@ "use strict"; | ||
// some urls were not parsing correctly (twitter.com) as they had ports included (twitter.com:443) | ||
// partially copied from isaacs/url-parse-as-address and optimised | ||
// partially copied from isaacs/url-parse-as-address and optimised. | ||
// | ||
// if uri contains 443 port so it's should be https, not http. | ||
// it's dumb way but suitable for most cases. | ||
var parseUrlOrAddress = function parseUrlOrAddress(uri) { | ||
var parsed = url.parse(uri, false); | ||
if (!parsed.slashes) { | ||
parsed = url.parse('http://' + uri, false); | ||
var prot = uri.indexOf(':443') > -1 ? "https://" : "http://"; | ||
parsed = url.parse(prot + uri, false); | ||
} else if (!parsed.protocol) { | ||
parsed = url.parse('http:' + uri, false); | ||
var prot = uri.indexOf(':443') > -1 ? "https:" : "http:"; | ||
parsed = url.parse(prot + uri, false); | ||
} | ||
@@ -98,3 +103,4 @@ | ||
version: version, | ||
index: line.index | ||
index: line.index, | ||
line: line.str | ||
}; | ||
@@ -119,3 +125,4 @@ }; | ||
message: message, | ||
index: line.index | ||
index: line.index, | ||
line: line.str | ||
}; | ||
@@ -122,0 +129,0 @@ }; |
@@ -7,5 +7,5 @@ "use strict"; | ||
var HTTPRequest = module.exports = function() { | ||
Request.apply(this); | ||
Request.call(this); | ||
this.protocol = 'HTTP'; | ||
}; | ||
util.inherits(HTTPRequest, Request); |
@@ -7,5 +7,4 @@ "use strict"; | ||
var HTTPResponse = module.exports = function() { | ||
Response.apply(this); | ||
this.protocol = 'HTTP'; | ||
Response.call(this, 'HTTP'); | ||
}; | ||
util.inherits(HTTPResponse, Response); |
"use strict"; | ||
var net = require('net'); | ||
var _ = require('lodash'); | ||
var ICAPError = require('./icap_error'); | ||
@@ -14,2 +12,4 @@ var ICAPRequest = require('./icap_request'); | ||
var assign = require('./utils').assign; | ||
var states = { | ||
@@ -26,2 +26,4 @@ 'icapmethod': 'icapmethod', | ||
var icapHandlerCount = 1; | ||
/* | ||
@@ -32,2 +34,5 @@ * ICAPHandler | ||
function ICAPHandler(socket, emitter, options) { | ||
this.handlerCount = '' + icapHandlerCount++; | ||
this.currentQuery = 0; | ||
this.id = ''; | ||
this.emitter = emitter; | ||
@@ -60,3 +65,3 @@ this.socket = socket; | ||
socket.on('data', function(data) { | ||
if (self.buffer.length == 0) { | ||
if (self.buffer.length === 0) { | ||
self.buffer = data; | ||
@@ -111,4 +116,3 @@ } else { | ||
} | ||
var id = process.pid + '::' + _.uniqueId(); | ||
this.id = id; | ||
this.id = process.pid + ':' + this.handlerCount + ':' + this.currentQuery++; | ||
this.state = states.icapmethod; | ||
@@ -194,3 +198,2 @@ this.icapRequest = new ICAPRequest(this.id); | ||
this.icapRequest.push(null); | ||
this.icapResponse.end(); | ||
this.resetState(); | ||
@@ -279,3 +282,3 @@ this.nextState(); | ||
this.logger.verbose('[%s] icapmethod %j', this.id, method, ''); | ||
this.logger.verbose('[%s] icapmethod:', this.id, method.line); | ||
this.emitEvent('icapMethod'); | ||
@@ -332,3 +335,3 @@ this.nextState(states.icapheader); | ||
this.httpRequest.setHeaders(headers); | ||
this.logger.verbose('[%s] requestheader %j', this.id, this.httpRequest, ''); | ||
this.logger.verbose('[%s] HTTP Req method: %s, headers: %j', this.id, method.line, headers, ''); | ||
if (this.icapRequest.isReqMod() && !this.parsePreview) { | ||
@@ -345,3 +348,3 @@ this.emitEvent('httpRequest'); | ||
} | ||
_.assign(this.httpResponse, status); | ||
assign(this.httpResponse, status); | ||
@@ -353,3 +356,3 @@ var headers = this.readAllHeaders(); | ||
this.httpResponse.setHeaders(headers); | ||
this.logger.verbose('[%s] responseheader %j', this.id, this.httpResponse, ''); | ||
this.logger.verbose('[%s] HTTP Res status: %s headers: %j', this.id, status.line, headers, ''); | ||
if (this.icapRequest.isRespMod() && !this.parsePreview) { | ||
@@ -403,3 +406,2 @@ this.emitEvent('httpResponse'); | ||
this.icapRequest.push(null); | ||
this.icapResponse.end(); | ||
this.resetState(); | ||
@@ -417,3 +419,2 @@ this.nextState(); | ||
this.icapRequest.push(null); | ||
this.icapResponse.end(); | ||
this.resetState(); | ||
@@ -420,0 +421,0 @@ this.nextState(); |
"use strict"; | ||
var util = require('util'); | ||
var _ = require('lodash'); | ||
var EventEmitter = require('eventemitter3'); | ||
var Request = require('./request'); | ||
var assign = require('./utils').assign; | ||
var magic = null; | ||
@@ -12,3 +14,3 @@ | ||
} catch (err) { | ||
console.warn('Can not import mmagic'); | ||
console.warn('Can not import mmmagic'); | ||
} | ||
@@ -18,17 +20,37 @@ | ||
Request.call(this); | ||
EventEmitter.call(this); | ||
this.id = id; | ||
this.stream = null; | ||
this.isPrevVersionProto = false; | ||
this.preview = null; | ||
this.ieof = false; | ||
this.done = false; | ||
}; | ||
util.inherits(ICAPRequest, Request); | ||
util.inherits(ICAPRequest, EventEmitter); | ||
_.assign(ICAPRequest.prototype, { | ||
assign(ICAPRequest.prototype, Request.prototype, { | ||
push: function(data) { | ||
if (this.stream) { | ||
this.stream._write(data); | ||
if (!this.stream) { | ||
// icapReq now are closed; | ||
if (data == null) { | ||
this.done = true; | ||
} | ||
return; | ||
} | ||
if (this.isPrevVersionProto) { | ||
return this.stream._write(data); | ||
} | ||
if (data) { | ||
return this.stream.write(data); | ||
} | ||
return this.stream.end(); | ||
}, | ||
pipe: function(stream) { | ||
this.stream = stream; | ||
this.isPrevVersionProto = stream.write == null; | ||
// icapReq are closed already thus we'are closing stream. | ||
if (this.done) { | ||
this.push(null); | ||
} | ||
}, | ||
@@ -58,4 +80,3 @@ hasPreview: function() { | ||
if (!this.preview) { | ||
cb(null, null); | ||
return; | ||
return cb(null, null); | ||
} | ||
@@ -65,4 +86,4 @@ if (magic != null) { | ||
} | ||
return cb(new Error("'mmagic' not loaded"), null); | ||
return cb(new Error("'mmmagic' not loaded"), null); | ||
} | ||
}); |
"use strict"; | ||
var util = require('util'); | ||
var _ = require('lodash'); | ||
var Transform = require('stream').Transform; | ||
var Response = require('./response'); | ||
var codes = require('./codes'); | ||
var currentISTag = "NODECAP-" + (new Date()).getTime(); | ||
var crlf = '\r\n'; | ||
var DEFAULT_CHUNK_SIZE = 4096; | ||
var assign = require('./utils').assign; | ||
var ICAPResponse = module.exports = function(id, stream, options) { | ||
Response.call(this); | ||
this.stream = stream; | ||
Response.call(this, 'ICAP'); | ||
options = assign(options || {}, { | ||
encoding: null, decodeStrings: true, | ||
objectMode: false, | ||
read: null, write: null, writev: null}); | ||
Transform.call(this, options); | ||
this.pipe(stream, {end: false}); | ||
this.id = id; | ||
this.protocol = 'ICAP'; | ||
this.done = false; | ||
this.filter = null; | ||
this.sendData = null; | ||
this.allowUnchangedAllowed = true; | ||
this.chunkSize = 'chunkSize' in options ? options.chunkSize : 4096; | ||
this.hasBody = false; | ||
this.chunkSize = 'chunkSize' in options ? options.chunkSize : DEFAULT_CHUNK_SIZE; | ||
this.icapStatus = null; | ||
this.icapHeaders = {}; | ||
this.httpMethodType = ''; | ||
this.httpMethod = null; | ||
@@ -26,7 +38,5 @@ this.httpHeaders = {}; | ||
}; | ||
util.inherits(ICAPResponse, Response); | ||
util.inherits(ICAPResponse, Transform); | ||
ICAPResponse.continueEvent = 'continueEvent'; | ||
_.assign(ICAPResponse.prototype, { | ||
assign(ICAPResponse.prototype, Response.prototype, { | ||
_getCode: function(code, options) { | ||
@@ -41,3 +51,4 @@ code = code || 500; | ||
setIcapHeaders: function(headers) { | ||
this.icapHeaders = _.assign(this.icapHeaders, headers); | ||
// TODO: filter headers??? | ||
this.icapHeaders = assign(this.icapHeaders, headers); | ||
}, | ||
@@ -49,3 +60,3 @@ setHttpMethod: function(options) { | ||
setHttpStatus: function(code, options) { | ||
if (_.isObject(code)) { | ||
if (typeof code === 'object') { | ||
options = code; | ||
@@ -60,3 +71,3 @@ code = options.code || null; | ||
setHttpHeaders: function(headers) { | ||
this.httpHeaders = _.assign(this.httpHeaders, headers); | ||
this.httpHeaders = assign(this.httpHeaders, headers); | ||
}, | ||
@@ -66,8 +77,8 @@ hasFilter: function() { | ||
}, | ||
setFilter: function(isBuffer, filterFn) { | ||
if (typeof isBuffer === 'function') { | ||
filterFn = isBuffer; | ||
isBuffer = false; | ||
setFilter: function(callAtEnd, filterFn) { | ||
if (typeof callAtEnd === 'function') { | ||
filterFn = callAtEnd; | ||
callAtEnd = false; | ||
} | ||
this.buffer = isBuffer ? new Buffer(0) : null; | ||
this.buffer = callAtEnd ? new Buffer(0) : null; | ||
this.filter = filterFn; | ||
@@ -79,8 +90,9 @@ }, | ||
var value = headers[key]; | ||
key += ": "; | ||
if (Array.isArray(value)) { | ||
for (var i = 0, l=value.length; i< l; ++i) { | ||
block += key + ": " + value[i] + crlf; | ||
for (var i = 0, l=value.length; i < l; ++i) { | ||
block += key + value[i] + crlf; | ||
} | ||
} else { | ||
block += key + ": " + value + crlf; | ||
block += key + value + crlf; | ||
} | ||
@@ -90,28 +102,21 @@ } | ||
}, | ||
writeHeaders: function(hasBody) { | ||
var headerBlock = ''; | ||
if (!this.icapStatus) { | ||
// TODO: user should always call setIcapStatusCode(), could throw error | ||
this.setIcapStatusCode(); | ||
_setEncapsulatedHeader: function(hasBody, headerBlock) { | ||
var encapsulated = []; | ||
var bodyType = "null-body"; | ||
if (this.httpMethodType === 'request') { | ||
encapsulated.push('req-hdr=0'); | ||
if (hasBody) { | ||
bodyType = 'req-body'; | ||
} | ||
} else { | ||
encapsulated.push('res-hdr=0'); | ||
if (hasBody) { | ||
bodyType = 'res-body'; | ||
} | ||
} | ||
encapsulated.push(bodyType + '=' + headerBlock.length); | ||
this.icapHeaders['Encapsulated'] = encapsulated.join(', '); | ||
}, | ||
// http status/headers | ||
if (!!this.httpMethodType) { | ||
headerBlock = this._joinHeaders(this.httpMethod, this.httpHeaders) + crlf; | ||
var encapsulated = []; | ||
var bodyType = "null-body"; | ||
if (this.httpMethodType === 'request') { | ||
encapsulated.push('req-hdr=0'); | ||
if (hasBody) { | ||
bodyType = 'req-body'; | ||
} | ||
} else { | ||
encapsulated.push('res-hdr=0'); | ||
if (hasBody) { | ||
bodyType = 'res-body'; | ||
} | ||
} | ||
encapsulated.push(bodyType + '=' + headerBlock.length); | ||
this.icapHeaders['Encapsulated'] = encapsulated.join(', '); | ||
} | ||
_checkDefaultIcapHeaders: function() { | ||
this.icapHeaders['Date'] = (new Date()).toGMTString(); | ||
@@ -124,74 +129,128 @@ if (!this.icapHeaders['ISTag']) { | ||
} | ||
}, | ||
writeHeaders: function(hasBody) { | ||
this.hasBody = hasBody; | ||
if (!this.icapStatus) { | ||
// TODO: user should always call setIcapStatusCode(), could throw error | ||
this.setIcapStatusCode(); | ||
} | ||
// http status/headers | ||
var headerBlock = ''; | ||
if (!!this.httpMethodType) { | ||
headerBlock = this._joinHeaders(this.httpMethod, this.httpHeaders) + crlf; | ||
this._setEncapsulatedHeader(hasBody, headerBlock); | ||
} | ||
// icap status/headers | ||
this._checkDefaultIcapHeaders() | ||
var icapBlock = this._joinHeaders(this.icapStatus, this.icapHeaders); | ||
this.stream.write(icapBlock + crlf + headerBlock); | ||
this.push(icapBlock + crlf + headerBlock); | ||
}, | ||
allowUnchanged: function(icapResponse) { | ||
if (this.allowUnchangedAllowed) { | ||
this.setIcapStatusCode(204); | ||
this.writeHeaders(false); | ||
this.end(); | ||
} | ||
// user should check status 204 is allowed own | ||
this.setIcapStatusCode(204); | ||
this.writeHeaders(false); | ||
this.end(); | ||
}, | ||
continuePreview: function() { | ||
var code = this._getCode(100); | ||
this.stream.write(code.join(' ') + crlf + crlf); | ||
this.push(code.join(' ') + crlf + crlf); | ||
}, | ||
_write: function(data) { | ||
var tmp; | ||
if (data) { | ||
if (this.buffer) { | ||
this.buffer = Buffer.concat([this.buffer, data], this.buffer.length + data.length); | ||
_writeHandyChunk: function(data) { | ||
// filter output and abort if no response | ||
// note: this allows filter authors to buffer data internally | ||
if (this.filter) { | ||
data = this.filter(data); | ||
if (!data) { | ||
return; | ||
} | ||
if (this.chunkSize && data.length > this.chunkSize) { | ||
var size = this.chunkSize; // 4096 bytes by default | ||
tmp = data.slice(0, size); | ||
data = data.slice(size); | ||
while (tmp.length) { | ||
this._write(tmp); | ||
tmp = data.slice(0, size); | ||
data = data.slice(size); | ||
} | ||
return; | ||
} | ||
// data are always Buffer instance due to 'decodeStrings: true' option. | ||
this.push(data.length.toString(16) + crlf); | ||
this.push(data); | ||
this.push(crlf); | ||
}, | ||
// TODO: more async | ||
_divideIntoHandyChunks: function(data, cb) { | ||
var size = this.chunkSize; | ||
var tmp = data.slice(0, size); | ||
data = data.slice(size); | ||
while (tmp.length) { | ||
this._writeHandyChunk(tmp); | ||
tmp = data.slice(0, size); | ||
data = data.slice(size); | ||
} | ||
return cb(); | ||
}, | ||
_writeChunk: function(data, cb) { | ||
if (this.buffer) { | ||
// TODO: maybe concat in buffer | ||
this.buffer = Buffer.concat([this.buffer, data], this.buffer.length + data.length); | ||
return cb(); | ||
} | ||
if (data.length > this.chunkSize) { | ||
return this._divideIntoHandyChunks(data, cb); | ||
} | ||
this._writeHandyChunk(data); | ||
return cb(); | ||
}, | ||
// alert the filter that stream is over | ||
// can return data to write it before the stream is ended | ||
_streamIsOver: function() { | ||
if (this.filter && this.buffer) { | ||
var data = this.filter(this.buffer); | ||
this.filter = null; | ||
this.buffer = null; | ||
if (data) { | ||
this.write(data); | ||
} | ||
// filter output and abort if no reponse | ||
// note: this allows filter authors to buffer data internally | ||
// and call response.send(data) once filter receives a `null` | ||
if (this.filter) { | ||
data = this.filter(data); | ||
} | ||
this.push('0\r\n\r\n'); | ||
}, | ||
_transform: function(data, _, cb) { | ||
// not write null chunks because they signal about end of stream | ||
if (data.length) { | ||
return this._writeChunk(data, cb); | ||
} | ||
return cb(); | ||
}, | ||
// TODO: legacy, remove from next version | ||
_write: function(data, enc, cb) { | ||
if (cb == null) { | ||
if (data) { | ||
this.write(data); | ||
} else { | ||
this.end(); | ||
} | ||
// ensure that data is in buffer form for accurate length measurements | ||
// and to avoid encoding issues when writing | ||
tmp = data instanceof Buffer ? data : new Buffer(data); | ||
this.stream.write(tmp.length.toString(16) + crlf); | ||
this.stream.write(tmp); | ||
this.stream.write(crlf); | ||
} else { | ||
// alert the filter that stream is over | ||
// can return data to write it before the stream is ended | ||
if (this.filter && this.buffer) { | ||
data = this.filter(this.buffer); | ||
this.filter = null; | ||
this.buffer = null; | ||
this._write(data); | ||
} | ||
this.stream.write('0\r\n\r\n'); | ||
return; | ||
} | ||
return Transform.prototype._write.call(this, data, enc, cb); | ||
}, | ||
send: function(data) { | ||
this.sendData = data; | ||
}, | ||
end: function() { | ||
if (this.done) { | ||
return; | ||
_flush: function(cb) { | ||
if (this.hasBody) { | ||
if (this.sendData) { | ||
this.write(this.sendData); | ||
this.sendData = null; | ||
} | ||
this._streamIsOver(); | ||
} | ||
if (this.sendData) { | ||
this._write(this.sendData); | ||
this._write(null); | ||
this.sendData = null; | ||
} | ||
this.done = true; | ||
this.unpipe(); | ||
cb(); | ||
} | ||
}); |
@@ -5,9 +5,10 @@ "use strict"; | ||
var util = require('util'); | ||
var _ = require('lodash'); | ||
var winston = require('winston'); | ||
var EventEmitter2 = require('eventemitter2').EventEmitter2; | ||
var EventEmitter = require('eventemitter3'); | ||
var ICAPHandler = require('./icap_handler'); | ||
var DomainList = require('./domainlist'); | ||
var noop = function() {}; | ||
var _utils = require('./utils'); | ||
var noop = _utils.noop; | ||
var assign = _utils.assign; | ||
@@ -18,6 +19,3 @@ /* | ||
function ICAPServer(options) { | ||
EventEmitter2.call(this, { | ||
wildcard: true, | ||
delimiter: '/' | ||
}); | ||
EventEmitter.call(this); | ||
this.id = util.format('[%d::server]', process.pid); | ||
@@ -33,6 +31,6 @@ this.logger = options.logger || new winston.Logger({ | ||
options = _.defaults(options || {}, { | ||
options = assign({ | ||
logger: this.logger, | ||
chunkSize: 4096 | ||
}); | ||
}, options || {}); | ||
@@ -46,3 +44,3 @@ this.server = net.createServer(function(stream) { | ||
this.errorCallbacks = []; | ||
this._errorCallbacks = []; | ||
this.on('error', function(err, icapReq, icapRes) { | ||
@@ -60,3 +58,3 @@ function next() { | ||
ix = 0; | ||
cbs = this.errorCallbacks; | ||
cbs = this._errorCallbacks; | ||
next(); | ||
@@ -71,7 +69,7 @@ } catch (e) { | ||
} finally { | ||
this.logger.error('%s ERROR - %s - %s', this.id, (icapRes.icapStatus || [null,null,null]).join(' '), err.message || 'Unknown Error'); | ||
this.logger.error('%s ERROR - httpmethod: %s - err: %s', this.id, (icapRes.httpMethod || []).join(' '), err.stack || err.message || 'Unknown Error'); | ||
} | ||
}.bind(this)); | ||
}, this); | ||
this.optionsCallbacks = []; | ||
this._optionsCallbacks = []; | ||
this.on('icapOptions', function(icapReq, icapRes) { | ||
@@ -93,12 +91,12 @@ function next() { | ||
ix = 0; | ||
cbs = this.optionsCallbacks; | ||
cbs = this._optionsCallbacks; | ||
pathname = icapReq.parsedUri.pathname; | ||
next(); | ||
this.logger.info('%s OPTIONS - %s %s', this.id, (icapRes.icapStatus || [null,null,null]).join(' '), (icapRes.httpMethod || [null,null,null]).join(' ')); | ||
this.logger.info('%s OPTIONS - %s - %s', this.id, (icapRes.icapStatus || []).join(' '), (icapRes.httpMethod || []).join(' ')); | ||
} catch (e) { | ||
this.emit('error', e, icapReq, icapRes); | ||
} | ||
}.bind(this)); | ||
}, this); | ||
this.requestCallbacks = []; | ||
this._requestCallbacks = []; | ||
this.on('httpRequest', function(icapReq, icapRes, req, res) { | ||
@@ -120,12 +118,12 @@ function next() { | ||
ix = 0; | ||
cbs = this.requestCallbacks; | ||
cbs = this._requestCallbacks; | ||
host = req.parsedUri.hostname; | ||
next(); | ||
this.logger.info('%s REQMOD - %s - %s %s - %s', this.id, (icapRes.icapStatus || [null,null,null]).join(' '), req.method, req.parsedUri.protocol + '//' + req.parsedUri.host + req.parsedUri.pathname, (icapRes.httpMethod || [null,null,null]).join(' ')); | ||
this.logger.info('%s REQMOD - %s - %s - %s', this.id, (icapRes.icapStatus || []).join(' '), req.line, (icapRes.httpMethod || []).join(' ')); | ||
} catch (e) { | ||
this.emit('error', e, icapReq, icapRes); | ||
} | ||
}.bind(this)); | ||
}, this); | ||
this.responseCallbacks = []; | ||
this._responseCallbacks = []; | ||
this.on('httpResponse', function(icapReq, icapRes, req, res) { | ||
@@ -147,13 +145,13 @@ function next() { | ||
ix = 0; | ||
cbs = this.responseCallbacks; | ||
cbs = this._responseCallbacks; | ||
host = req.parsedUri.hostname; | ||
next(); | ||
this.logger.info('%s RESPMOD - %s - %s %s - %s', this.id, (icapRes.icapStatus || [null,null,null]).join(' '), req.method, req.parsedUri.protocol + '//' + req.parsedUri.host + req.parsedUri.pathname, (icapRes.httpMethod || [null,null,null]).join(' ')); | ||
this.logger.info('%s RESPMOD - %s - %s - %s', this.id, (icapRes.icapStatus || []).join(' '), req.line, (icapRes.httpMethod || []).join(' ')); | ||
} catch (e) { | ||
this.emit('error', e, icapReq, icapRes); | ||
} | ||
}.bind(this)); | ||
}, this); | ||
} | ||
ICAPServer.prototype = _.assign({}, EventEmitter2.prototype, { | ||
ICAPServer.prototype = assign({}, EventEmitter.prototype, { | ||
constructor: ICAPServer, | ||
@@ -177,3 +175,6 @@ | ||
error: function(cb) { | ||
this.errorCallbacks.push(cb); | ||
if (typeof cb != 'function') { | ||
throw new TypeError("expected function, not " + typeof cb); | ||
} | ||
this._errorCallbacks.push(cb); | ||
}, | ||
@@ -187,3 +188,6 @@ | ||
} | ||
this.optionsCallbacks.push([path, cb]); | ||
if (typeof cb != "function") { | ||
throw new TypeError("expected function, not " + typeof cb); | ||
} | ||
this._optionsCallbacks.push([path, cb]); | ||
}, | ||
@@ -201,3 +205,6 @@ | ||
} | ||
this.requestCallbacks.push([domainList, cb]); | ||
if (typeof cb != "function") { | ||
throw new TypeError("expected function, not " + typeof cb); | ||
} | ||
this._requestCallbacks.push([domainList, cb]); | ||
}, | ||
@@ -215,3 +222,6 @@ | ||
} | ||
this.responseCallbacks.push([domainList, cb]); | ||
if (typeof cb != "function") { | ||
throw new TypeError("expected function, not " + typeof cb); | ||
} | ||
this._responseCallbacks.push([domainList, cb]); | ||
} | ||
@@ -218,0 +228,0 @@ }); |
"use strict"; | ||
var util = require('util'); | ||
var _ = require('lodash'); | ||
var EventEmitter2 = require('eventemitter2').EventEmitter2; | ||
var assign = require('./utils').assign; | ||
// use as mixin, not classical inheritance | ||
var Request = module.exports = function() { | ||
EventEmitter2.call(this, {}); | ||
this.headers = null; | ||
this.method = ''; | ||
this.line = ''; // line that parsed to method, uri etc | ||
this.uri = null; | ||
@@ -15,5 +14,4 @@ this.version = null; | ||
}; | ||
util.inherits(Request, EventEmitter2); | ||
_.assign(Request.prototype, { | ||
assign(Request.prototype, { | ||
setHeaders: function(headers) { | ||
@@ -24,6 +22,6 @@ if (!this.headers) { | ||
} | ||
_.assign(this.headers, headers); | ||
assign(this.headers, headers); | ||
}, | ||
setMethod: function(method) { | ||
_.assign(this, method); | ||
assign(this, method); | ||
if (!this.parsedUri) { | ||
@@ -30,0 +28,0 @@ this.parsedUri = { |
"use strict"; | ||
var util = require('util'); | ||
var _ = require('lodash'); | ||
var EventEmitter2 = require('eventemitter2').EventEmitter2; | ||
var assign = require('./utils').assign; | ||
var Response = module.exports = function(stream) { | ||
EventEmitter2.call(this, {}); | ||
// use as mixin, not classical inheritance | ||
var Response = module.exports = function(protocol) { | ||
this.headers = {}; | ||
this.protocol = ''; | ||
this.protocol = protocol || ""; | ||
this.version = ''; | ||
this.code = 200; | ||
}; | ||
util.inherits(Response, EventEmitter2); | ||
_.assign(Response.prototype, { | ||
assign(Response.prototype, { | ||
setHeaders: function(headers) { | ||
@@ -22,4 +19,4 @@ if (!this.headers) { | ||
} | ||
_.assign(this.headers, headers); | ||
assign(this.headers, headers); | ||
} | ||
}); |
@@ -11,3 +11,3 @@ var helpers = require('./spec_helpers'); | ||
console.log('response'); | ||
throw new Error('TEST_REQUEST_ERROR'); | ||
throw new Error('TEST_RESPONSE_ERROR'); | ||
}); | ||
@@ -14,0 +14,0 @@ |
var helpers = require('./spec_helpers'); | ||
helpers.testIO('ICAPRequest should get mime type of preview', 'mime', function(t, server, cb) { | ||
server.response('*', function(icapReq, icapRes, req, res, next) { | ||
@@ -14,3 +13,5 @@ t.ok(icapReq.hasPreview(), 'should have a preview'); | ||
}); | ||
next(); | ||
}); | ||
}); |
@@ -14,8 +14,10 @@ var fs = require('fs'); | ||
var sampleDir = 'samples/'; | ||
var noop = function() {}; | ||
var testIO = function(testName, sampleName, configureFn) { | ||
var testIO = function(testName, sampleName, configureFn, configureInput) { | ||
configureFn = typeof configureFn === 'function' ? configureFn : null; | ||
var input = fs.readFileSync(path.resolve(__dirname, sampleName + '.in.txt'), 'utf8'); | ||
var output = fs.readFileSync(path.resolve(__dirname, sampleName + '.out.txt'), 'utf8'); | ||
var input = fs.readFileSync(path.resolve(__dirname, sampleDir + sampleName + '.in.txt'), 'utf8'); | ||
var output = fs.readFileSync(path.resolve(__dirname, sampleDir + sampleName + '.out.txt'), 'utf8'); | ||
@@ -35,3 +37,2 @@ test(testName, function(t) { | ||
} | ||
t.end(); | ||
}; | ||
@@ -43,2 +44,5 @@ | ||
} | ||
if (configureInput) { | ||
input = configureInput(input); | ||
} | ||
@@ -57,3 +61,3 @@ exampleConfig(server); | ||
client.on('error', function(err) { | ||
console.error(err); | ||
console.error("CLIENT ERROR", err); | ||
if (err.stack) { | ||
@@ -66,11 +70,9 @@ console.error(err.stack); | ||
client.end(); | ||
// console.log(output); | ||
// console.log(buffer); | ||
buffer = buffer.replace(datePattern, dateReplace).replace(istagPattern, istagReplace); | ||
output = output.replace(datePattern, dateReplace).replace(istagPattern, istagReplace); | ||
//console.error("BUFFER:", buffer); | ||
//console.error("OUTPUT:", output); | ||
t.equal(buffer, output, 'should have expected icap responses'); | ||
server.close(function() { | ||
if (!configureFn) { | ||
t.end(); | ||
} | ||
t.end(); | ||
}); | ||
@@ -77,0 +79,0 @@ }, 1000); |
@@ -55,7 +55,2 @@ var ICAPServer = require('../').ICAPServer; | ||
server.response('*', function(icapReq, icapRes, req, res, next) { | ||
// handle previews before doing anything else: icapReq.preview is buffer of preview data | ||
if (icapReq.hasPreview()) { | ||
icapRes.continuePreview(); | ||
return; | ||
} | ||
icapRes.setIcapStatusCode(200); | ||
@@ -67,2 +62,7 @@ icapRes.setIcapHeaders(icapReq.headers); | ||
icapReq.pipe(icapRes); | ||
// handle previews before doing anything else: icapReq.preview is buffer of preview data | ||
if (icapReq.hasBody() && !icapReq.ieof) { | ||
icapRes.continuePreview(); | ||
return; | ||
} | ||
}); | ||
@@ -69,0 +69,0 @@ |
@@ -26,2 +26,3 @@ var helpers = require('./spec_helpers'); | ||
icapRes.send('NO'); | ||
icapRes.end(); | ||
}); | ||
@@ -28,0 +29,0 @@ |
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
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
91607
3
54
2213
104
+ Addedeventemitter3@^1.2.0
+ Addedeventemitter3@1.2.0(transitive)
+ Addedmmmagic@0.4.6(transitive)
- Removedeventemitter2@^0.4.14
- Removedlodash@^4.3.0
- Removedeventemitter2@0.4.14(transitive)
- Removedmmmagic@0.3.16(transitive)
Updatedwinston@^2.2.0