README
synchronous express-like middleware using fibext/fibers
Express-like middleware, but the middleware stack is run in sync(like koa, javaee filter).
use fibext or fibers to make the code run in sequence/sync.
simple and with an principle:
- (mostly) add members other than change the node original request/response api
- keep consistent with node
Installation
npm install --save tier
Simple usage
var tier = require('tier');
var fibext = require('fibext');
var app = tier();
app.use(function(req, resp, next){//error middleware
try{
next();
}catch(e){
resp.statusCode = 500;
resp.end(e.message);
}
});
app.use(function(req, resp, next){//logger middleware
console.log('before request');
next();
console.log('after request');
});
app.use(function(req, resp, next){//used with async code
var start = Date.now();
var fiber = fibext();
setTimeout(function(){
fiber.resume();
}, 1000);
fiber.wait();
resp.write('wake up after %s ms', Date.now()-start);
});
app.listen(8080);
Use existing express middleware
Generally, tier is compatible with most express middlewares, and you are appreciated to porting the existing express middlewares for easy use
var bodyParser = require('body-parser');
app.use(function(req, resp, next){
fibext.run(bodyParser.urlencoded(), req, resp);
fibext.run(bodyParser.json(), req, resp);
fibext.run(bodyParser.text(), req, resp);
next();
});
More usages
Please refer to the test cases to get more usage examples.
Router
In tier, a router instance is a middleware function too! so, anywhere a middleware can be placed, same as router instance. then you can use nested routers, use router with other middleware functions, and so on.
router has two types of methods, one is router.use
, which will match the path pattern just from the beginning, another is router.all|get|post
, which should match the whole path pattern. see:
router().use('/a', ...); //will match any url with /a prefix, like /a, /a/b
router().all('/a', ...); //will only match the url /a, not for /a/b
Usage examples:
var router = tier.builtin.router;
var r = router();//create a router instance
r.use(function(req, resp, next){//all passed
next();
}).get('/', function(req, resp, next){//only for root url and GET method
next();
}).all('/', function(req, resp, next){//only for root url, and any request method
next();
});
app.use(r);
router.use|all|get|post([path], middleware, middleware, ...)
- path: the path pattern. like express, see path-to-regexp. if ignored, it will be attached on the root(/). use
req.params
to retrieve the named parameter in path pattern. - middleware: multiple. can be a function or a router instance.
Supported HTTP methods: get
, post
, put
, delete
, head
, options
, patch
, search
.
Built-in middlewares
There are some built-in middlewares. each middleware may attach some properties/functions in the req or resp. like:
app.use(tier.builtin.url());
app.use(function(err, req, resp){
console.log(req.query);
});
router(options)
options has:
params
: the default params for any request matched in this router. usereq.params
to access the param.
see #Router for usage.
url()
req.protocol
, req.href
, req.host
, req.hostname
, req.port
, req.pathname
, req.path
, req.query
, req.search
, req.extname
ip(proxy)
req.ip
, req.ips
accept()
req.accept
is an instance of accepts
redirect(options)
options has:
- root: the web root url. if resp.redirect with a partial url(like /p/a/t/h), then root will be used to generate full url.
resp.redirect(url[, params])
send()
resp.type(type, charset)
, resp.send()
, resp.json()
, resp.sendStatus(code, message)
, resp.download(filePath, filename)
resp.sendFile(filePath, options)
. see static
middleware's options.
static(options)
options:
root
: required. the root dir of the static files. defaultprocess.cwd()
maxAge
: ms. supportms
moduleindex
: when request a directory(with trailing slash /), send "index.html" file under the dirdirectory
: when pathname is a directory(without trailing slash /), send 404 by default. set it toredirect
to append trailing slash / and then redirect or set it tothrow
to throw an errorheaders
: object of header name/value pairs
if file not found, an error will be thrown. so wrap it with try...catch
block.
session(options)
currently not support secure cookie. options:
ttl
: the max age(ms) of the session. the expired time will be refreshed when accessingreq.session
secret
: required. used to sign the cookie valuename
: the cookie name, defaulttier.sid
cookie
: default{path: '/', httpOnly: true}
after add this middleware, use req.session
to access session object. it has id
, destroy()
and regenerate()
properties. these properties cannot be overwrited.
Coverage
run command npm run test-cov
.
=============================== Coverage summary ===============================
Statements : 97.07% ( 430/443 )
Branches : 90.37% ( 197/218 )
Functions : 98.36% ( 60/61 )
Lines : 97.57% ( 402/412 )
================================================================================
License
Licensed under MIT
Copyright (c) 2015 kiliwalk