Comparing version 0.11.0-rc5 to 0.11.0
@@ -8,2 +8,18 @@ # Nodecaf Changelog | ||
## [v0.11.0] - 2020-11-20 | ||
### Added | ||
- constructor option to build a custom web server | ||
- `app.trigger()` method to call routes programatically bypassing HTTP layer | ||
- `all()` handler function to match all routes in a fall back style | ||
### Changed | ||
- http server to be optional | ||
- a few log types for | ||
- error hangling behavor to spit errors on respose body on DEV environment only | ||
### Removed | ||
- HTTPS/SSL configurations and feature | ||
- WS endpoints feature | ||
## [v0.10.1] - 2020-08-10 | ||
@@ -10,0 +26,0 @@ |
const assert = require('assert'); | ||
const { METHODS } = require('http'); | ||
const { pathToRegexp } = require('path-to-regexp'); | ||
const cookieSignature = require('cookie-signature'); | ||
@@ -50,2 +51,3 @@ const resMethods = require('./response'); | ||
function runHandler(input, handler){ | ||
if(input.res.stackAborted) | ||
@@ -88,2 +90,14 @@ return; | ||
function parseSignedCookies(cconf, input){ | ||
for(let key in input.cookies) | ||
// TODO 's:' needed?? | ||
if(input.cookies[key].substr(0, 2) == 's:'){ | ||
let val = cookieSignature.unsign(input.cookies[key].substr(2), cconf.secret); | ||
if(val){ | ||
input.signedCookies[key] = val; | ||
delete input.cookies[key]; | ||
} | ||
} | ||
} | ||
module.exports = class API { | ||
@@ -141,10 +155,11 @@ | ||
let app = this.context; | ||
app.log.debug({ type: 'request' }, 'Received %s request for %s', method, path); | ||
let handler = matchRoute.apply(this, [ method, path, params ]); | ||
let app = this.context; | ||
let res = generateResponseObject(method, path); | ||
input = { | ||
...app.global, conf: app.conf, res, flash: {}, | ||
...app.global, conf: app.conf, res, flash: {}, cookies: {}, | ||
headers: {}, query: {}, ...input, params, log: app.log | ||
@@ -157,2 +172,7 @@ }; | ||
if(app.conf.cookie) | ||
input.res.cookieSecret = app.conf.cookie.secret; | ||
input.signedCookies = {}; | ||
parseSignedCookies(app.conf.cookie, input); | ||
let masterPromise = new Promise(resolve => { | ||
@@ -159,0 +179,0 @@ input.res.routeEnded = resolve; |
const { URL } = require('url'); | ||
const cookie = require('cookie'); | ||
const querystring = require('querystring'); | ||
const cookie = require('cookie'); | ||
const cookieSignature = require('cookie-signature'); | ||
const http = require('http'); | ||
@@ -27,15 +25,2 @@ const { parseBody } = require('./parser'); | ||
function parseCookies(cconf, req){ | ||
req.cookies = cookie.parse(req.headers.cookie); | ||
req.signedCookies = {}; | ||
for(let key in req.cookies) | ||
if(req.cookies[key] && req.cookies[key].substr(0, 2) == 's:'){ | ||
let val = cookieSignature.unsign(req.cookies[key].substr(2), cconf.secret); | ||
if(val){ | ||
req.signedCookies[key] = val; | ||
delete req.cookies[key]; | ||
} | ||
} | ||
} | ||
async function prepareHandling(app, req, res){ | ||
@@ -49,6 +34,3 @@ req.hasBody = Boolean(req.headers['content-length']); | ||
if(app.conf.cookie) | ||
req.secret = app.conf.cookie.secret; | ||
if(req.headers.cookie) | ||
parseCookies(app.conf.cookie, req); | ||
req.cookies = cookie.parse(req.headers.cookie || ''); | ||
@@ -77,3 +59,4 @@ if(app.conf.cors) | ||
await this._api.trigger(req.method, req.path, { | ||
query: req.query, req, res, headers: req.headers, body: req.body | ||
query: req.query, req, res, headers: req.headers, body: req.body, | ||
cookies: req.cookies | ||
}); | ||
@@ -85,3 +68,4 @@ } | ||
async startServer(){ | ||
this._server = http.createServer(handleRequest.bind(this)); | ||
let handler = handleRequest.bind(this); | ||
this._server = this._serverBuilder(this).on('request', handler); | ||
await new Promise(done => this._server.listen(this.conf.port, done)); | ||
@@ -88,0 +72,0 @@ this.log.info({ type: 'server' }, |
const | ||
http = require('http'), | ||
cors = require('cors'), | ||
Logger = require('golog'), | ||
assert = require('assert'), | ||
Confort = require('confort'), | ||
Logger = require('golog'), | ||
compression = require('compression'); | ||
@@ -37,2 +38,3 @@ | ||
this._shutdown = opts.shutdown || noop; | ||
this._serverBuilder = opts.server || (() => http.createServer()); | ||
@@ -51,2 +53,5 @@ let { name, version } = findPkgInfo(); | ||
new TypeError('Shutdown handler must be a function')); | ||
assert(typeof this._serverBuilder == 'function', | ||
new TypeError('Server builder must be a function')); | ||
} | ||
@@ -137,6 +142,8 @@ | ||
// Stop listening; Run shutdown handler; Wait actual http close | ||
if(this._server) | ||
await new Promise(done => this._server.close(done)); | ||
var closedPromise = new Promise(done => this._server.close(done)); | ||
await this._shutdown(this); | ||
await closedPromise; | ||
await this._shutdown(this); | ||
delete this.global; | ||
@@ -143,0 +150,0 @@ |
@@ -97,3 +97,3 @@ const { sign } = require('cookie-signature'); | ||
if(opts.signed && !this.req.secret) | ||
if(opts.signed && !this.cookieSecret) | ||
throw new Error('Trying to sign cookies when secret is not defined'); | ||
@@ -104,3 +104,3 @@ | ||
if(opts.signed) | ||
value = 's:' + sign(value, this.req.secret); | ||
value = 's:' + sign(value, this.cookieSecret); | ||
@@ -107,0 +107,0 @@ if('maxAge' in opts) { |
{ | ||
"name": "nodecaf", | ||
"version": "0.11.0-rc5", | ||
"version": "0.11.0", | ||
"description": "Nodecaf is a light framework for developing RESTful Apps in a quick and convenient manner.", | ||
@@ -49,4 +49,3 @@ "main": "lib/main.js", | ||
"raw-body": "^2.4.1", | ||
"stdout-stream": "^1.4.1", | ||
"ws": "^7.3.1" | ||
"stdout-stream": "^1.4.1" | ||
}, | ||
@@ -53,0 +52,0 @@ "devDependencies": { |
# [Nodecaf](https://gitlab.com/GCSBOSS/nodecaf) | ||
> Docs for version v0.10.x. | ||
> Docs for version v0.11.x. | ||
@@ -18,3 +18,2 @@ Nodecaf is a light framework for developing RESTful Apps in a quick and convenient manner. | ||
- Shortcut for [CORS Settings](#cors) on all routes. | ||
- [HTTPS capability](#https). | ||
- Functions to [describe your API](#api-description) making your code the main | ||
@@ -134,3 +133,3 @@ source of truth. | ||
- external services data such as database credentials | ||
- Nodecaf settings such as SSL and logging | ||
- Nodecaf settings such as cors and logging | ||
- Your own server application settings for your users | ||
@@ -360,16 +359,2 @@ | ||
### HTTPS | ||
In production it's generally desirable to have an HTTPS setup for both client to | ||
API and API to API communications. You can enable SSL for your server by adding | ||
a `ssl` key to your config, containing both the path for your key and cert. | ||
```toml | ||
[ssl] | ||
key = "/path/to/key.pem" | ||
cert = "/path/to/cert.pem" | ||
``` | ||
When SSL is enabled the default server port becomes 443. | ||
### Filter Requests by Mime-type | ||
@@ -376,0 +361,0 @@ |
filefoobar |
@@ -420,5 +420,5 @@ const assert = require('assert'); | ||
get('/bar', function({ req, res }){ | ||
res.badRequest(req.cookies.testa !== 'bar'); | ||
res.badRequest(req.signedCookies.test !== 'foo'); | ||
get('/bar', function({ res, cookies, signedCookies }){ | ||
res.badRequest(cookies.testa !== 'bar'); | ||
res.badRequest(signedCookies.test !== 'foo'); | ||
res.end(); | ||
@@ -450,2 +450,25 @@ }); | ||
it('Should not read cookies with wrong signature', async function(){ | ||
let app = new Nodecaf({ | ||
conf: { port: 80, cookie: { secret: 'OH YEAH' } }, | ||
api({ get }){ | ||
get('/foo', function({ res }){ | ||
res.cookie('test', 'foo', { signed: true, maxAge: 5000 }); | ||
res.end(); | ||
}); | ||
get('/bar', function({ res, signedCookies }){ | ||
res.badRequest(signedCookies.test !== 'foo'); | ||
res.end(); | ||
}); | ||
} | ||
}); | ||
await app.start(); | ||
let { cookies } = await base.get('foo'); | ||
cookies['test'] = cookies['test'].substring(0, cookies['test'].length - 1) + '1'; | ||
let { status } = await base.get('bar', { cookies }); | ||
assert.strictEqual(status, 400); | ||
await app.stop(); | ||
}); | ||
it('Should clear cookies', async function(){ | ||
@@ -452,0 +475,0 @@ let app = new Nodecaf({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
91490
11
23
1363
0
450