Comparing version 0.9.1 to 0.9.2
@@ -8,2 +8,18 @@ # Nodecaf Changelog | ||
## [v0.9.2] - 2020-06-23 | ||
### Added | ||
- ws connection error handler interface | ||
### Fixed | ||
- uncaught error when request is aborted during body reading | ||
- error while calling `stop()` during startup process | ||
### Changed | ||
- logger to use non-blocking I/O | ||
- all websocket log entries to debug level | ||
### Removed | ||
- date leaving only time on log entries in dev env | ||
## [v0.9.1] - 2020-04-16 | ||
@@ -351,1 +367,2 @@ | ||
[v0.9.1]: https://gitlab.com/GCSBOSS/nodecaf/-/tags/v0.9.1 | ||
[v0.9.2]: https://gitlab.com/GCSBOSS/nodecaf/-/tags/v0.9.2 |
@@ -154,4 +154,6 @@ const | ||
return false; | ||
this.active = true; | ||
let active; | ||
this.active = new Promise(r => active = r); | ||
if(this.conf.delay > 0) | ||
@@ -180,2 +182,3 @@ await new Promise(done => setTimeout(done, this.conf.delay)); | ||
active(); | ||
return this; | ||
@@ -190,2 +193,4 @@ } | ||
return false; | ||
await this.active; | ||
this.active = false; | ||
@@ -192,0 +197,0 @@ |
const util = require('util'); | ||
const stdout = require('stdout-stream'); | ||
const LEVELS = { | ||
@@ -17,4 +18,5 @@ debug: { w: 0, c: '\x1b[30;5;1m' }, | ||
let uword = (entry.class == 'event' ? entry.level : entry.class).toUpperCase(); | ||
let utime = '[' + entry.time.toString().split(' ').slice(0, 5).join(' ') + ']'; | ||
console.log(LEVELS[entry.level].c + utime, uword, '-', entry.msg + '\x1b[0m'); | ||
entry.time.setMinutes(entry.time.getMinutes() - entry.time.getTimezoneOffset()); | ||
let utime = entry.time.toISOString().slice(11, -5); | ||
stdout.write(LEVELS[entry.level].c + utime + ': ' + uword + ' - ' + entry.msg + '\x1b[0m\n'); | ||
} | ||
@@ -25,3 +27,3 @@ | ||
else if(env !== 'testing') | ||
console.log(JSON.stringify(entry)); | ||
stdout.write(JSON.stringify(entry) + '\n'); | ||
} | ||
@@ -33,5 +35,5 @@ | ||
let msg = util.format(...args); | ||
let klass = data.class || ''; | ||
return { ...data, pid: process.pid, level, msg, time, class: klass || 'event' }; | ||
let klass = data.class || 'event'; | ||
let pid = process.pid != 1 ? process.pid : null; | ||
return { ...data, pid, level, msg, time, class: klass }; | ||
} | ||
@@ -38,0 +40,0 @@ |
@@ -57,3 +57,5 @@ const assert = require('assert'); | ||
encoding: req.contentCharset | ||
}); | ||
}).catch(/* istanbul ignore next */ err => | ||
this.log.warn({ req, err, class: 'request' }, 'Filed to parse request body')); | ||
console.log(req.body); | ||
next(); | ||
@@ -60,0 +62,0 @@ } |
@@ -26,3 +26,3 @@ const WebSocket = require('ws'); | ||
let route = app.wsRoutes[req.pathname]; | ||
app.log.ws(client, req, 'info', 'New connection from %s'); | ||
app.log.ws(client, req, 'debug', 'New connection from %s'); | ||
@@ -35,6 +35,12 @@ client.on('message', message => { | ||
client.on('close', () => { | ||
app.log.ws(client, req, 'info', 'Closed connection from %s'); | ||
app.log.ws(client, req, 'debug', 'Closed connection from %s'); | ||
route.close(args); | ||
}); | ||
/* istanbul ignore next */ | ||
client.on('error', err => { | ||
app.log.ws(client, req, 'error', 'Error in connection to %s'); | ||
route.error({ ...args, err }); | ||
}); | ||
route.connect(args); | ||
@@ -52,3 +58,3 @@ } | ||
if(! (req.pathname in app.wsRoutes) ){ | ||
app.log.ws(socket, req, 'info', 'Dropped connection to unkown path from %s'); | ||
app.log.ws(socket, req, 'debug', 'Dropped connection to unkown path from %s'); | ||
socket.destroy(); | ||
@@ -72,9 +78,10 @@ } | ||
assert(!spec.close || typeof spec.close == 'function', new TypeError('Close handler must be a function')); | ||
assert(!spec.error || typeof spec.error == 'function', new TypeError('Error handler must be a function')); | ||
app.wsRoutes = app.wsRoutes || {}; | ||
let connect = message = close = Function.prototype; | ||
app.wsRoutes[path] = { connect, message, close, ...spec }; | ||
let connect = message = close = error = Function.prototype; | ||
app.wsRoutes[path] = { error, connect, message, close, ...spec }; | ||
} | ||
}; |
{ | ||
"name": "nodecaf", | ||
"version": "0.9.1", | ||
"version": "0.9.2", | ||
"description": "Nodecaf is a framework on top of Express for building RESTful services in a quick and convenient manner.", | ||
@@ -44,2 +44,3 @@ "main": "lib/main.js", | ||
"mime": "^2.4.4", | ||
"stdout-stream": "^1.4.1", | ||
"ws": "^7.2.1" | ||
@@ -46,0 +47,0 @@ }, |
@@ -240,5 +240,7 @@ # [Nodecaf](https://gitlab.com/GCSBOSS/nodecaf) | ||
| server | info | The server configuration has been reloaded | | ||
| websocket | info | A new websocket connection happened | | ||
| websocket | debug | A new websocket connection happened | | ||
| websocket | debug | A message was received | | ||
| websocket | info | A websocket connection was closed | | ||
| websocket | debug | A websocket connection was closed | | ||
| websocket | debug | Rejected a websocket connection to invalid path | | ||
| websocket | error | An error happened with a websocket connection | | ||
@@ -365,2 +367,3 @@ Additionally, you can filter log entries by level and class with the following | ||
|--------|--------------------| | ||
| `exist` | `NotFound` | | ||
| `valid` | `InvalidContent` | | ||
@@ -440,3 +443,3 @@ | `authorized` | `Unauthorized` | | ||
1. `path`: where the websocket will be accessible | ||
2. `events`: object containing any of the following handlers: `connect`, `message`, `close`. | ||
2. `events`: object containing any of the following handlers: `connect`, `message`, `close`, `error`. | ||
@@ -451,11 +454,13 @@ ```js | ||
ws('/my-path-1', { | ||
connect: (client, req) => console.log('NEW CLIENT'), | ||
message: (message, client, req) => console.log('NEW MESSAGE'), | ||
close: (client, req) => console.log('BYE CLIENT') | ||
connect: ({ client }) => console.log('NEW CLIENT'), | ||
message: ({ message, client }) => console.log('NEW MESSAGE'), | ||
close: ({ client }) => console.log('BYE CLIENT'), | ||
error: ({ err, client }) => console.log('I FEEL ODD') | ||
}); | ||
ws('/my-path-2', { | ||
connect: (client, req) => console.log('NEW CLIENT 2'), | ||
message: (message, client, req) => console.log('NEW MESSAGE 2'), | ||
close: (client, req) => console.log('BYE CLIENT 2') | ||
connect: ({ client }) => console.log('NEW CLIENT 2'), | ||
message: ({ message, client }) => console.log('NEW MESSAGE 2'), | ||
close: ({ client }) => console.log('BYE CLIENT 2'), | ||
error: ({ err, client }) => console.log('I FEEL ODD 2') | ||
}); | ||
@@ -468,2 +473,4 @@ | ||
Besides the ones showing, the following handler args are present in all ws handlers: `client`, `req`, `flash`, `conf`, `log`, `headers`, `query` and exposed vars. | ||
### Filter Requests by Mime-type | ||
@@ -470,0 +477,0 @@ |
@@ -885,2 +885,10 @@ const assert = require('assert'); | ||
it('Should not fail when attempting to close during startup', async () => { | ||
let app = new AppServer(); | ||
let p = app.start(); | ||
await assert.doesNotReject( app.stop() ); | ||
await p; | ||
await app.stop(); | ||
}); | ||
}); | ||
@@ -899,2 +907,3 @@ | ||
connect: () => count++, | ||
error: Function.prototype, | ||
async message({ message }){ | ||
@@ -934,2 +943,26 @@ assert.strictEqual('foobar', message); | ||
// it('Should properly handle client errors', function(done){ | ||
// let app = new AppServer(); | ||
// app.api(({ ws }) => { | ||
// ws('/foo', { error: done }); | ||
// }); | ||
// (async function(){ | ||
// await app.start(); | ||
// let ws = new WebSocket('ws://localhost/foo'); | ||
// ws.destroy(); | ||
// })(); | ||
// }); | ||
// it('Should not fail when client breaks connection during req body read', async () => { | ||
// let app = new AppServer(); | ||
// app.api(function({ post }){ | ||
// post('/foo', Function.prototype); | ||
// }); | ||
// await app.start(); | ||
// let req = require('http').request(LOCAL_HOST + '/foo', { method: 'POST' }); | ||
// req.write(JSON.stringify([...Array(2048)].keys())); | ||
// req.abort(); | ||
// await app.stop(); | ||
// }); | ||
}); | ||
@@ -936,0 +969,0 @@ |
91711
1401
564
10
+ Addedstdout-stream@^1.4.1
+ Addedcore-util-is@1.0.3(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedstdout-stream@1.4.1(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)