commit
27d1336af5
4 changed files with 137 additions and 3 deletions
|
@ -59,6 +59,26 @@ http.createServer(app.callback()).listen(3001);
|
|||
Add the given middleware function to this application. See [Middleware](#middleware) for
|
||||
more information.
|
||||
|
||||
### app.keys=
|
||||
|
||||
Set signed cookie keys.
|
||||
|
||||
These are passed to [KeyGrip](https://github.com/jed/keygrip),
|
||||
however you may also pass your own `KeyGrip` instance. For
|
||||
example the following are acceptable:
|
||||
|
||||
```js
|
||||
app.keys = ['im a newer secret', 'i like turtle'];
|
||||
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
|
||||
```
|
||||
|
||||
These keys may be rotated and are used when signing cookies
|
||||
with the `{ signed: true }` option:
|
||||
|
||||
```js
|
||||
this.cookies.set('name', 'tobi', { signed: true });
|
||||
```
|
||||
|
||||
## Handling Requests
|
||||
|
||||
Koa requests are manipulated using a `Context` object containing both a Koa `Request` and `Response` object. For more information on these view:
|
||||
|
|
|
@ -10,6 +10,7 @@ var context = require('./context');
|
|||
var request = require('./request');
|
||||
var response = require('./response');
|
||||
var Cookies = require('cookies');
|
||||
var Keygrip = require('keygrip');
|
||||
var Stream = require('stream');
|
||||
var http = require('http');
|
||||
var co = require('co');
|
||||
|
@ -96,11 +97,42 @@ app.callback = function(){
|
|||
|
||||
return function(req, res, next){
|
||||
var ctx = self.createContext(req, res);
|
||||
|
||||
co.call(ctx, gen)(next || ctx.onerror);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set signed cookie keys.
|
||||
*
|
||||
* These are passed to [KeyGrip](https://github.com/jed/keygrip),
|
||||
* however you may also pass your own `KeyGrip` instance. For
|
||||
* example the following are acceptable:
|
||||
*
|
||||
* app.keys = ['im a newer secret', 'i like turtle'];
|
||||
* app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
|
||||
*
|
||||
* @param {Array|KeyGrip} keys
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.__defineSetter__('keys', function(keys){
|
||||
var ok = Array.isArray(keys) || keys instanceof Keygrip;
|
||||
if (!ok) throw new TypeError('app.keys must be an array or Keygrip');
|
||||
if (!(keys instanceof Keygrip)) keys = new Keygrip(keys);
|
||||
this._keys = keys;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get `Keygrip` instance.
|
||||
*
|
||||
* @return {Keygrip}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.__defineGetter__('keys', function(){
|
||||
return this._keys;
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize a new context.
|
||||
*
|
||||
|
@ -116,8 +148,8 @@ app.createContext = function(req, res){
|
|||
context.res = request.res = response.res = res;
|
||||
request.ctx = response.ctx = context;
|
||||
context.onerror = context.onerror.bind(context);
|
||||
context.cookies = new Cookies(req, res);
|
||||
context.originalUrl = request.originalUrl = req.url;
|
||||
context.cookies = new Cookies(req, res, this.keys);
|
||||
return context;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
"fresh": "~0.2.0",
|
||||
"negotiator": "~0.3.0",
|
||||
"koa-compose": "~2.0.0",
|
||||
"cookies": "~0.3.6"
|
||||
"cookies": "~0.3.6",
|
||||
"keygrip": "~0.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bytes": "~0.2.1",
|
||||
|
|
81
test/context/cookies.js
Normal file
81
test/context/cookies.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
var koa = require('../..')
|
||||
var request = require('supertest');
|
||||
|
||||
describe('ctx.cookies.set()', function(){
|
||||
it('should set an unsigned cookie', function(done){
|
||||
var app = koa();
|
||||
|
||||
app.use(function *(next){
|
||||
this.cookies.set('name', 'jon');
|
||||
this.status = 204;
|
||||
})
|
||||
|
||||
var server = app.listen();
|
||||
|
||||
request(server)
|
||||
.get('/')
|
||||
.expect(204)
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
|
||||
res.headers['set-cookie'].some(function(cookie){
|
||||
return /^name=/.test(cookie);
|
||||
}).should.be.ok;
|
||||
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
describe('with .signed', function(){
|
||||
describe('when no .keys are set', function(){
|
||||
it('should error', function(done){
|
||||
var app = koa();
|
||||
|
||||
app.use(function *(next){
|
||||
try {
|
||||
this.cookies.set('foo', 'bar', { signed: true });
|
||||
} catch (err) {
|
||||
this.body = err.message;
|
||||
}
|
||||
});
|
||||
|
||||
request(app.listen())
|
||||
.get('/')
|
||||
.expect('Cannot call method \'sign\' of undefined', done);
|
||||
})
|
||||
})
|
||||
|
||||
it('should send a signed cookie', function(done){
|
||||
var app = koa();
|
||||
|
||||
app.keys = ['a', 'b'];
|
||||
|
||||
app.use(function *(next){
|
||||
this.cookies.set('name', 'jon', { signed: true });
|
||||
this.status = 204;
|
||||
})
|
||||
|
||||
var server = app.listen();
|
||||
|
||||
request(server)
|
||||
.get('/')
|
||||
.expect(204)
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
|
||||
var cookies = res.headers['set-cookie'];
|
||||
|
||||
cookies.some(function(cookie){
|
||||
return /^name=/.test(cookie);
|
||||
}).should.be.ok;
|
||||
|
||||
cookies.some(function(cookie){
|
||||
return /^name\.sig=/.test(cookie);
|
||||
}).should.be.ok;
|
||||
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue