xprezzo-connect
Advanced tools
Comparing version 1.1.0 to 1.1.2
@@ -0,1 +1,17 @@ | ||
1.1.1 / 2022-05-11 | ||
================== | ||
* depds: updated | ||
* depds xprezzo-mixin updated to v.1.1.2 | ||
* depds eslint updated to 8.15.0 | ||
* depds eslint-config-standard updated to 17.0.0 | ||
* depds eslint-plugin-import updated to 2.26.0 | ||
* depds eslint-plugin-markdown updated to 2.2.1 | ||
* depds eslint-plugin-promise updated to 6.0.0 | ||
* depds nyc updated to 15.1.0 | ||
* depds supertest updated to 6.2.3 | ||
* remove eslint-plugin-standard | ||
* depds xprezzo-debug updated to v.1.1.1 | ||
* depds xprezzo-finalhandler updated to v1.1.1 | ||
1.1.0 / 2020-10-15 | ||
@@ -5,3 +21,11 @@ ================== | ||
* depds: updated | ||
* depds xprezzo-mixin updated to v.1.1.1 | ||
* depds xprezzo-debug updated to v.1.1.1 | ||
* depds xprezzo-finalhandler updated to v1.1.1 | ||
1.1.0 / 2020-10-15 | ||
================== | ||
* depds: updated | ||
1.0.0 / 2020-10-15 | ||
@@ -8,0 +32,0 @@ ================== |
439
index.js
/*! | ||
* xprezzo-connect | ||
* Copyright(c) Ben Ajenoui <info@seohero.io> | ||
* Copyright(c) Cloudgen Wong <cloudgen.wong@gmail.com> | ||
* MIT Licensed | ||
@@ -13,272 +13,267 @@ */ | ||
*/ | ||
const debug = require('xprezzo-debug')('xprezzo:connect') | ||
const EventEmitter = require('events').EventEmitter | ||
const finalhandler = require('xprezzo-finalhandler') | ||
const mixin = require('xprezzo-mixin') | ||
const http = require('http') | ||
const parseUrl = require('parseurl') | ||
var debug = require('xprezzo-debug')('xprezzo:connect'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var finalhandler = require('xprezzo-finalhandler'); | ||
var mixin = require('xprezzo-mixin'); | ||
var http = require('http'); | ||
var parseUrl = require('parseurl'); | ||
let env = process.env.NODE_ENV || 'development' | ||
/* istanbul ignore next */ | ||
let defer = typeof setImmediate === 'function' | ||
? setImmediate | ||
: (fn) => { | ||
process.nextTick(fn.bind.apply(fn, arguments)) | ||
} | ||
/** | ||
* Module exports. | ||
* @public | ||
* Invoke a route handle. | ||
* @private | ||
*/ | ||
let call = (handle, route, err, req, res, next) => { | ||
let arity = handle.length | ||
let error = err | ||
let hasError = Boolean(err) | ||
debug('%s %s : %s', handle.name || '<anonymous>', route, req.originalUrl) | ||
try { | ||
if (hasError && arity === 4) { | ||
// error-handling middleware | ||
handle(err, req, res, next) | ||
return; | ||
} else if (!hasError && arity < 4) { | ||
// request-handling middleware | ||
handle(req, res, next) | ||
return | ||
} | ||
} catch (e) { | ||
// replace the error | ||
error = e | ||
} | ||
// continue | ||
next(error) | ||
} | ||
module.exports = createServer; | ||
/** | ||
* Module variables. | ||
* Log error using console.error. | ||
* | ||
* @param {Error} err | ||
* @private | ||
*/ | ||
var env = process.env.NODE_ENV || 'development'; | ||
var proto = {}; | ||
let logerror = (err) => { | ||
if (env !== 'test') | ||
console.error(err.stack || err.toString()) | ||
} | ||
/* istanbul ignore next */ | ||
var defer = typeof setImmediate === 'function' | ||
? setImmediate | ||
: function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } | ||
/** | ||
* Create a new connect server. | ||
* Get get protocol + host for a URL. | ||
* | ||
* @return {function} | ||
* @public | ||
* @param {string} url | ||
* @private | ||
*/ | ||
function createServer() { | ||
debug('start'); | ||
function app(req, res, next){ app.handle(req, res, next); } | ||
mixin(app, proto, EventEmitter.prototype,{ | ||
route : '/', | ||
stack : [] | ||
}); | ||
if(typeof app.init === 'function'){ | ||
debug('call proto init()'); | ||
app.init(); | ||
} | ||
return app; | ||
debug('done'); | ||
let getProtohost = (url) => { | ||
if (url.length === 0 || url[0] === '/') { | ||
return undefined | ||
} | ||
let fqdnIndex = url.indexOf('://') | ||
return fqdnIndex !== -1 && url.lastIndexOf('?', fqdnIndex) === -1 | ||
? url.substr(0, url.indexOf('/', 3 + fqdnIndex)) | ||
: undefined | ||
} | ||
/** | ||
* Utilize the given middleware `handle` to the given `route`, | ||
* defaulting to _/_. This "route" is the mount-point for the | ||
* middleware, when given a value other than _/_ the middleware | ||
* is only effective when that segment is present in the request's | ||
* pathname. | ||
* Create a new connect server. | ||
* | ||
* For example if we were to mount a function at _/admin_, it would | ||
* be invoked on _/admin_, and _/admin/settings_, however it would | ||
* not be invoked for _/_, or _/posts_. | ||
* | ||
* @param {String|Function|Server} route, callback or server | ||
* @param {Function|Server} callback or server | ||
* @return {Server} for chaining | ||
* @return {function} | ||
* @public | ||
*/ | ||
let createServer = () => { | ||
debug('start'); | ||
let app = (req, res, next) => { | ||
app.handle(req, res, next) | ||
} | ||
mixin(app, proto, EventEmitter.prototype,{ | ||
route : '/', | ||
stack : [] | ||
}); | ||
if(typeof app.init === 'function'){ | ||
debug('call proto init()') | ||
app.init() | ||
} | ||
debug('done') | ||
return app | ||
} | ||
proto.use = function use(route, fn) { | ||
var handle = fn; | ||
var path = route; | ||
// default route to '/' | ||
if (typeof route !== 'string') { | ||
handle = route; | ||
path = '/'; | ||
} | ||
// wrap sub-apps | ||
if (typeof handle.handle === 'function') { | ||
var server = handle; | ||
server.route = path; | ||
handle = function (req, res, next) { | ||
server.handle(req, res, next); | ||
}; | ||
} | ||
// wrap vanilla http.Servers | ||
if (handle instanceof http.Server) { | ||
handle = handle.listeners('request')[0]; | ||
} | ||
// strip trailing slash | ||
if (path[path.length - 1] === '/') { | ||
path = path.slice(0, -1); | ||
} | ||
// add the middleware | ||
debug('use %s %s', path || '/', handle.name || 'anonymous'); | ||
this.stack.push({ route: path, handle: handle }); | ||
return this; | ||
}; | ||
/** | ||
* Handle server requests, punting them down | ||
* the middleware stack. | ||
* | ||
* Module variables. | ||
* @private | ||
*/ | ||
let proto = { | ||
/** | ||
* Utilize the given middleware `handle` to the given `route`, | ||
* defaulting to _/_. This "route" is the mount-point for the | ||
* middleware, when given a value other than _/_ the middleware | ||
* is only effective when that segment is present in the request's | ||
* pathname. | ||
* | ||
* For example if we were to mount a function at _/admin_, it would | ||
* be invoked on _/admin_, and _/admin/settings_, however it would | ||
* not be invoked for _/_, or _/posts_. | ||
* | ||
* @param {String|Function|Server} route, callback or server | ||
* @param {Function|Server} callback or server | ||
* @return {Server} for chaining | ||
* @public | ||
*/ | ||
use : function (route, fn) { | ||
let handle = fn | ||
let path = route | ||
proto.handle = function handle(req, res, out) { | ||
var index = 0; | ||
var protohost = getProtohost(req.url) || ''; | ||
var removed = ''; | ||
var slashAdded = false; | ||
var stack = this.stack; | ||
// default route to '/' | ||
if (typeof route !== 'string') { | ||
handle = route | ||
path = '/' | ||
} | ||
// final function handler | ||
var done = out || finalhandler(req, res, { | ||
env: env, | ||
onerror: logerror | ||
}); | ||
// wrap sub-apps | ||
if (typeof handle.handle === 'function') { | ||
let server = handle | ||
server.route = path | ||
handle = function (req, res, next) { | ||
server.handle(req, res, next) | ||
} | ||
} | ||
// store the original URL | ||
req.originalUrl = req.originalUrl || req.url; | ||
// wrap vanilla http.Servers | ||
if (handle instanceof http.Server) { | ||
handle = handle.listeners('request')[0]; | ||
} | ||
function next(err) { | ||
if (slashAdded) { | ||
req.url = req.url.substr(1); | ||
slashAdded = false; | ||
} | ||
// strip trailing slash | ||
if (path[path.length - 1] === '/') { | ||
path = path.slice(0, -1) | ||
} | ||
if (removed.length !== 0) { | ||
req.url = protohost + removed + req.url.substr(protohost.length); | ||
removed = ''; | ||
} | ||
// add the middleware | ||
debug('use %s %s', path || '/', handle.name || 'anonymous') | ||
this.stack.push({ route: path, handle: handle }) | ||
// next callback | ||
var layer = stack[index++]; | ||
return this | ||
}, | ||
// all done | ||
if (!layer) { | ||
defer(done, err); | ||
return; | ||
} | ||
/** | ||
* Handle server requests, punting them down | ||
* the middleware stack. | ||
* | ||
* @private | ||
*/ | ||
handle : function(req, res, out) { | ||
let index = 0 | ||
let protohost = getProtohost(req.url) || '' | ||
let removed = '' | ||
let slashAdded = false | ||
let stack = this.stack | ||
// route data | ||
var path = parseUrl(req).pathname || '/'; | ||
var route = layer.route; | ||
// final function handler | ||
let done = out || finalhandler(req, res, { | ||
env: env, | ||
onerror: logerror | ||
}) | ||
// skip this layer if the route doesn't match | ||
if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) { | ||
return next(err); | ||
} | ||
// store the original URL | ||
req.originalUrl = req.originalUrl || req.url | ||
// skip if route match does not border "/", ".", or end | ||
var c = path.length > route.length && path[route.length]; | ||
if (c && c !== '/' && c !== '.') { | ||
return next(err); | ||
} | ||
let next = (err) => { | ||
if (slashAdded) { | ||
req.url = req.url.substr(1) | ||
slashAdded = false | ||
} | ||
// trim off the part of the url that matches the route | ||
if (route.length !== 0 && route !== '/') { | ||
removed = route; | ||
req.url = protohost + req.url.substr(protohost.length + removed.length); | ||
if (removed.length !== 0) { | ||
req.url = protohost + removed + req.url.substr(protohost.length) | ||
removed = '' | ||
} | ||
// ensure leading slash | ||
if (!protohost && req.url[0] !== '/') { | ||
req.url = '/' + req.url; | ||
slashAdded = true; | ||
} | ||
} | ||
// next callback | ||
let layer = stack[index++] | ||
// call the layer handle | ||
call(layer.handle, route, err, req, res, next); | ||
} | ||
// all done | ||
if (!layer) { | ||
defer(done, err) | ||
return | ||
} | ||
next(); | ||
}; | ||
// route data | ||
let path = parseUrl(req).pathname || '/' | ||
let route = layer.route | ||
/** | ||
* Listen for connections. | ||
* | ||
* This method takes the same arguments | ||
* as node's `http.Server#listen()`. | ||
* | ||
* HTTP and HTTPS: | ||
* | ||
* If you run your application both as HTTP | ||
* and HTTPS you may wrap them individually, | ||
* since your Connect "server" is really just | ||
* a JavaScript `Function`. | ||
* | ||
* var connect = require('connect') | ||
* , http = require('http') | ||
* , https = require('https'); | ||
* | ||
* var app = connect(); | ||
* | ||
* http.createServer(app).listen(80); | ||
* https.createServer(options, app).listen(443); | ||
* | ||
* @return {http.Server} | ||
* @api public | ||
*/ | ||
// skip this layer if the route doesn't match | ||
if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) { | ||
return next(err) | ||
} | ||
proto.listen = function listen() { | ||
var server = http.createServer(this); | ||
return server.listen.apply(server, arguments); | ||
}; | ||
// skip if route match does not border "/", ".", or end | ||
let c = path.length > route.length && path[route.length] | ||
if (c && c !== '/' && c !== '.') { | ||
return next(err) | ||
} | ||
/** | ||
* Invoke a route handle. | ||
* @private | ||
*/ | ||
// trim off the part of the url that matches the route | ||
if (route.length !== 0 && route !== '/') { | ||
removed = route | ||
req.url = protohost + req.url.substr(protohost.length + removed.length) | ||
function call(handle, route, err, req, res, next) { | ||
var arity = handle.length; | ||
var error = err; | ||
var hasError = Boolean(err); | ||
// ensure leading slash | ||
if (!protohost && req.url[0] !== '/') { | ||
req.url = '/' + req.url | ||
slashAdded = true | ||
} | ||
} | ||
// call the layer handle | ||
call(layer.handle, route, err, req, res, next) | ||
} | ||
next() | ||
}, | ||
debug('%s %s : %s', handle.name || '<anonymous>', route, req.originalUrl); | ||
/** | ||
* Listen for connections. | ||
* | ||
* This method takes the same arguments | ||
* as node's `http.Server#listen()`. | ||
* | ||
* HTTP and HTTPS: | ||
* | ||
* If you run your application both as HTTP | ||
* and HTTPS you may wrap them individually, | ||
* since your Connect "server" is really just | ||
* a JavaScript `Function`. | ||
* | ||
* let connect = require('connect') | ||
* , http = require('http') | ||
* , https = require('https') | ||
* | ||
* let app = connect() | ||
* | ||
* http.createServer(app).listen(80) | ||
* https.createServer(options, app).listen(443) | ||
* | ||
* @return {http.Server} | ||
* @api public | ||
*/ | ||
try { | ||
if (hasError && arity === 4) { | ||
// error-handling middleware | ||
handle(err, req, res, next); | ||
return; | ||
} else if (!hasError && arity < 4) { | ||
// request-handling middleware | ||
handle(req, res, next); | ||
return; | ||
listen : function() { | ||
let server = http.createServer(this) | ||
return server.listen.apply(server, arguments) | ||
} | ||
} catch (e) { | ||
// replace the error | ||
error = e; | ||
} | ||
// continue | ||
next(error); | ||
} | ||
/** | ||
* Log error using console.error. | ||
* | ||
* @param {Error} err | ||
* @private | ||
*/ | ||
function logerror(err) { | ||
if (env !== 'test') console.error(err.stack || err.toString()); | ||
} | ||
/** | ||
* Get get protocol + host for a URL. | ||
* | ||
* @param {string} url | ||
* @private | ||
* Module exports. | ||
* @public | ||
*/ | ||
function getProtohost(url) { | ||
if (url.length === 0 || url[0] === '/') { | ||
return undefined; | ||
} | ||
var fqdnIndex = url.indexOf('://') | ||
return fqdnIndex !== -1 && url.lastIndexOf('?', fqdnIndex) === -1 | ||
? url.substr(0, url.indexOf('/', 3 + fqdnIndex)) | ||
: undefined; | ||
} | ||
module.exports = createServer |
{ | ||
"name": "xprezzo-connect", | ||
"description": "High performance middleware framework", | ||
"version": "1.1.0", | ||
"author": "Ben Ajenoui <info@seohero.io>", | ||
"version": "1.1.2", | ||
"author": "Cloudgen Wong <cloudgen.wong@gmail.com>", | ||
"keywords": [ | ||
@@ -16,11 +16,16 @@ "framework", | ||
"parseurl": "~1.3.3", | ||
"xprezzo-mixin": "1.1.0", | ||
"xprezzo-debug": "1.1.0", | ||
"xprezzo-finalhandler": "1.1.0" | ||
"xprezzo-mixin": "1.1.2", | ||
"xprezzo-debug": "1.1.2", | ||
"xprezzo-finalhandler": "1.1.1" | ||
}, | ||
"devDependencies": { | ||
"eslint": "7.8.1", | ||
"mocha": "8.1.3", | ||
"nyc": "15.0.1", | ||
"supertest": "4.0.2" | ||
"eslint": "8.15.0", | ||
"eslint-config-standard": "17.0.0", | ||
"eslint-plugin-import": "2.26.0", | ||
"eslint-plugin-markdown": "2.2.1", | ||
"eslint-plugin-node": "~11.1.0", | ||
"eslint-plugin-promise": "6.0.0", | ||
"mocha": "10.0.0", | ||
"nyc": "15.1.0", | ||
"supertest": "6.2.3" | ||
}, | ||
@@ -27,0 +32,0 @@ "license": "MIT", |
@@ -217,3 +217,3 @@ #xprezzo-connect | ||
Xprezzo and related projects are maintained by [Ben Ajenoui](mailto:info@seoher.io) and sponsored by [SEO Hero](https://www.seohero.io). | ||
Xprezzo and related projects are maintained by [Cloudgen Wong](mailto:cloudgen.wong@gmail.com). | ||
@@ -220,0 +220,0 @@ ## License |
Sorry, the diff of this file is not supported yet
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
16481
243
9
2
+ Addedxprezzo-debug@1.1.11.1.2(transitive)
+ Addedxprezzo-finalhandler@1.1.1(transitive)
+ Addedxprezzo-mixin@1.1.2(transitive)
+ Addedxprezzo-on-finished@1.1.1(transitive)
+ Addedxprezzo-stream-unpipe@1.0.0(transitive)
- Removedee-first@1.1.1(transitive)
- Removedunpipe@1.0.0(transitive)
- Removedxprezzo-debug@1.1.0(transitive)
- Removedxprezzo-finalhandler@1.1.0(transitive)
- Removedxprezzo-mixin@1.1.0(transitive)
- Removedxprezzo-on-finished@1.1.0(transitive)
Updatedxprezzo-debug@1.1.2
Updatedxprezzo-finalhandler@1.1.1
Updatedxprezzo-mixin@1.1.2