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

nodecaf

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nodecaf - npm Package Compare versions

Comparing version 0.11.13 to 0.12.0-rc1

CHANGELOG.md

64

lib/api.js

@@ -5,4 +5,4 @@ const assert = require('assert');

const resMethods = require('./response');
const { handleError } = require('./error');
const Response = require('./response');
const RequestBody = require('./body');

@@ -86,38 +86,5 @@

handler(input).catch(err => handleError(err, input));
handler(input).catch(err => handleError(err, input.res));
}
function generateResponseObject(method, url, req){
return {
headers: {},
req,
statusCode: 200,
end(body){
let output = { status: this.statusCode, headers: this.headers };
if(body)
output.body = body;
this.input.log.debug({ res: this });
this.finished = true;
return this.routeEnded(output);
},
getHeader(key){
return this.headers[key]
},
setHeader(key, value){
this.headers[key] = value;
}
};
}
function generateRequestObject(method, path, input){
let obj = { method, path };
input.headers && Object.assign(obj, input.headers);
return obj;
}
function parseSignedCookies(cconf, input){

@@ -209,21 +176,17 @@ for(let key in input.cookies)

const req = input.req = input.req || generateRequestObject(method, path, input);
const res = input.res = input.res || generateResponseObject(method, path, req);
res.req = req;
res.input = input;
Object.assign(res, resMethods);
let origReq = input.req || {};
input.req = { method, path, host: origReq.host, 'user-agent': origReq['user-agent'] };
app.log.debug({ req: input.req });
app.log.debug({ req });
let res = input.res = new Response(input);
const handler = matchRoute.call(this, method, path, params);
const masterPromise = new Promise(done => { res.routeEnded = done });
if(!handler){
res.status(404).end();
return masterPromise;
return res.ended;
}
req.body = input.body = new RequestBody(input);
if(app._shouldParseBody)
input.body = new RequestBody(input, origReq);
if(app._autoParseBody)
try{

@@ -233,8 +196,7 @@ input.body = await input.body.parse();

catch(err){
!req.aborted && res.status(400).end();
return app.log.warn({ req, err, type: 'request' });
res.status(400).end();
app.log.warn({ req: res.req, err, type: 'request' });
return res.ended;
}
if(app.conf.cookie)
res.cookieSecret = app.conf.cookie.secret;
parseSignedCookies(app.conf.cookie, input);

@@ -250,5 +212,5 @@

return masterPromise;
return res.ended;
}
}

@@ -5,4 +5,2 @@

const formdata = require('./form-data');
const FALLBACK_CONTENT_TYPE = { type: 'text/plain', parameters: { charset: 'utf-8' } };

@@ -25,3 +23,3 @@

function readStream(){
var buffer = [];
var complete, buffer = [];

@@ -45,9 +43,9 @@ this.req.on('data', chunk => buffer.push(chunk));

this.req.on('end', () => {
!this.complete && resolve(Buffer.concat(buffer));
this.complete = true;
!complete && resolve(Buffer.concat(buffer));
complete = true;
});
this.req.on('error', err => {
!this.complete && reject(err);
this.complete = true;
!complete && reject(err);
complete = true;
});

@@ -59,3 +57,3 @@ });

if(!this.isStream)
if(!this.res.res)
return this.origBody;

@@ -73,10 +71,8 @@

constructor({ req, res, headers, body }){
constructor({ res, headers, body }, stream){
Object.assign(this, parseContentType(headers));
this.req = req;
this.req = stream;
this.res = res;
this.origBody = body;
this.complete = false;
this.length = headers['content-length'];
this.isStream = req.readable;
}

@@ -101,3 +97,2 @@

this.res.badType(this.type.slice(-4) != 'json');
return await read.call(this, raw =>

@@ -109,5 +104,2 @@ JSON.parse(raw.toString(this.textCharset)));

if(this.type == 'multipart/form-data')
return formdata(this.req);
if(this.type.slice(-4) == 'json')

@@ -114,0 +106,0 @@ return this.json();

@@ -25,10 +25,8 @@

// and from res.error() when calling it with an error
function handleError(err, input){
input.res.failed = true;
function handleError(err, res){
res.failed = true;
// Need to keep the original error stack and message for logging.
input.res.err = err;
res.err = err;
const { log, res } = input;
err = anythingToError(err);

@@ -39,4 +37,4 @@

log.error({ method: input.res.req.method, path: input.res.req.path,
headers: input.res.req.headers, type: 'route', err: input.res.err });
res.log.error({ method: res.req.method, path: res.req.path,
headers: res.req.headers, type: 'route', err: res.err });

@@ -43,0 +41,0 @@ if(!res.finished)

@@ -18,4 +18,2 @@ const cookie = require('cookie');

res.on('finish', () => this.log.debug({ res }));
await this._api.trigger(req.method, req.path, {

@@ -22,0 +20,0 @@ query: req.query, req, res, headers: req.headers, cookies: req.cookies

@@ -11,8 +11,2 @@ const

const SHORT_TYPES = {
form: 'multipart/form-data',
urlencoded: 'application/x-www-form-urlencoded',
json: 'application/json'
};
const noop = function(){};

@@ -68,3 +62,3 @@ noop.noop = true;

this._shouldParseBody = opts.shouldParseBody || typeof opts.shouldParseBody == 'undefined';
this._autoParseBody = opts.autoParseBody || false;
this._alwaysRebuildAPI = opts.alwaysRebuildAPI || false;

@@ -92,11 +86,2 @@

accept(types){
types = [].concat(types).map(t => SHORT_TYPES[t] || t);
return ({ body, req, res, next }) => {
if(body !== '' && !types.includes(req.body.type))
return res.status(415).end();
next();
}
}
async start(){

@@ -103,0 +88,0 @@

const { sign } = require('cookie-signature');
const cookie = require('cookie');
const { format } = require('util');
const { HTTPError, handleError } = require('./error');

@@ -20,51 +21,38 @@

badType: 415
}
};
function assert(status, cond, message, ...args){
if(!cond)
return true;
throw this.error(status, message, ...args);
}
module.exports = class Response {
module.exports = {
constructor({ res, req, log, conf }){
this.conf = conf;
this.res = res;
this.log = log;
this.req = req;
this.ended = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.headers = {};
this.statusCode = 200;
for(let name in ASSERTS)
this[name] = this.assert.bind(this, ASSERTS[name]);
}
get(k){
return this.getHeader(k);
},
write(chunk){
this.res && this.res.write(chunk);
this.body ? this.body.concat(chunk) : this.body = chunk;
}
set(k, v){
this.setHeader(k, v);
return this;
},
end(body){
this.body ? this.body.concat(body) : this.body = body;
this.res && this.res.end(body);
this.log.debug({ res: this });
this.finished = true;
return this.resolve({
status: this.statusCode,
headers: this.headers,
body: this.body
});
}
append(k, v){
let prev = this.get(k);
prev && (v = Array.isArray(prev)
? prev.concat(v)
: [ prev, v ]);
return this.set(k, v);
},
status(s){
this.statusCode = s;
return this;
},
type(ct){
this.set('Content-Type', SHORT_CONTENT_TYPES[ct] || ct);
return this;
},
json(data){
this.type('json');
this.end(JSON.stringify(data));
return this;
},
text(data){
this.type('text');
this.end(String(data));
return this;
},
// Not necessarily an APP error, but a client Error

@@ -75,3 +63,3 @@ error(status, message, ...args){

if(!Number.isInteger(status))
return handleError(status, this.input);
return handleError(status, this);

@@ -99,4 +87,47 @@ this.status(status);

return new HTTPError(status, message, type);
},
}
assert(status, cond, message, ...args){
if(!cond)
return true;
throw this.error(status, message, ...args);
}
set(k, v){
this.res && this.res.setHeader(k, v);
this.headers[k] = v;
return this;
}
append(k, v){
let prev = this.headers[k];
prev && (v = Array.isArray(prev)
? prev.concat(v)
: [ prev, v ]);
return this.set(k, v);
}
status(s){
this.res && (this.res.statusCode = s);
this.statusCode = s;
return this;
}
type(ct){
this.set('Content-Type', SHORT_CONTENT_TYPES[ct] || ct);
return this;
}
json(data){
this.type('json');
this.end(JSON.stringify(data));
return this;
}
text(data){
this.type('text');
this.end(String(data));
return this;
}
clearCookie(name, opts) {

@@ -106,3 +137,3 @@ opts = { path: '/', ...opts, expires: new Date(1) };

return this.cookie(name, '', opts);
},
}

@@ -113,3 +144,3 @@ cookie(name, value, opts = {}) {

if(opts.signed && !this.cookieSecret)
if(opts.signed && !this.conf.cookie?.secret)
throw new Error('Trying to sign cookies when secret is not defined');

@@ -120,3 +151,3 @@

if(opts.signed)
value = 's:' + sign(value, this.cookieSecret);
value = 's:' + sign(value, this.conf.cookie.secret);

@@ -133,9 +164,4 @@ if('maxAge' in opts) {

};
}
for(let name in ASSERTS)
module.exports[name] = function(...args){
assert.call(this, ASSERTS[name], ...args);
}
// TODO 406 notAcceptable:

@@ -142,0 +168,0 @@ // TODO 405 methodNotAllowed

{
"name": "nodecaf",
"version": "0.11.13",
"version": "0.12.0-rc1",
"description": "Nodecaf is a light framework for developing RESTful Apps in a quick and convenient manner.",

@@ -40,3 +40,2 @@ "main": "lib/main.js",

"dependencies": {
"busboy": "^0.3.1",
"confort": "^0.2.0",

@@ -50,3 +49,2 @@ "content-type": "^1.0.4",

"devDependencies": {
"form-data": "^3.0.1",
"muhb": "^3.0.4",

@@ -53,0 +51,0 @@ "toml": "^3.0.0"

@@ -20,3 +20,2 @@ # [Nodecaf](https://gitlab.com/GCSBOSS/nodecaf)

source of truth.
- Functions to [filter request bodies](#filter-requests-by-mime-type) by mime-type.
- Helpful [command line interface](https://gitlab.com/GCSBOSS/nodecaf-cli).

@@ -419,38 +418,2 @@

### Filter Requests by Mime-type
Nodecaf allow you to reject request bodies whose mime-type is not in a defined
white-list. Denied requests will receive a 400 response with the apporpriate
message.
Define a filter for the entire app on your `api.js`:
```js
module.exports = function({ }){
this.accept(['json', 'text/html']);
}
```
Override the global accept per route on your `api.js`:
```js
const { accept } = require('nodecaf');
module.exports = function({ post, put }){
// Define global accept rules
this.accept(['json', 'text/html']);
// Obtain accepts settings
let json = accept('json');
let img = accept([ 'png', 'jpg', 'svg', 'image/*' ]);
// Prepend accept definition in each route chain
post('/my/json/thing', json, myJSONHandler);
post('/my/img/thing', img, myImageHandler);
}
```
### API Description

@@ -507,3 +470,2 @@

| `app.conf.port` | Integer | Port for the web server to listen (also exposed as user conf) | `80` or `443` |
| `app.conf.formFileDir` | Path | Where to store files uploaded as form-data | OS default temp dir |
| `app.conf.cookie.secret` | String | A secure random string to be used for signing cookies | none |

@@ -510,0 +472,0 @@ | `opts.name` | String | Manually set application name used in various places | `package.json`s |

Sorry, the diff of this file is not supported yet

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