Skip to content

Commit

Permalink
Closes hapijs#782
Browse files Browse the repository at this point in the history
  • Loading branch information
Eran Hammer committed Apr 20, 2013
1 parent dc11f93 commit f710547
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 48 deletions.
7 changes: 3 additions & 4 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,8 @@ server.route({ method: 'GET', path: '/', config: { auth: 'simple' } });
Cookie authentication provides a simple cookie-based session management. The user has to be authenticated via other means, typically a web
form, and upon successful authentication, receive a reply with a session cookie. Subsequent requests containing the session cookie are authenticated
(the cookie uses [Iron](https://github.com/hueniverse/iron) to encrypt and sign the session content) and validated via the provided `validateFunc`
in case the cookie's encrypted content requires validation on each request. Note that cookie operates as a plain text secret with the property that
anyone in possession of the cookie content can use it to imperssonate its true owner. The `'cookie`' scheme takes the following required options:
in case the cookie's encrypted content requires validation on each request. Note that cookie operates as a bearer token and anyone in possession
of the cookie content can use it to imperssonate its true owner. The `'cookie`' scheme takes the following required options:
- `scheme` - set to `'cookie'`.
- `cookie` - the cookie name. Defaults to `'sid'`.
- `password` - used for Iron cookie encoding.
Expand Down Expand Up @@ -767,8 +767,7 @@ server.auth('session', {

http.route([
{ method: 'GET', path: '/', config: { handler: home, auth: true } },
{ method: 'GET', path: '/login', config: { handler: login, auth: { mode: 'try' } } },
{ method: 'POST', path: '/login', config: { handler: login, auth: { mode: 'try' } } },
{ method: '*', path: '/login', config: { handler: login, auth: { mode: 'try' } } },
{ method: 'GET', path: '/logout', config: { handler: logout, auth: true } }
]);

Expand Down
37 changes: 18 additions & 19 deletions examples/cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,53 @@ internals.users = {
};


internals.home = function (request) {
internals.home = function () {

request.reply('<html><head><title>Login page</title></head><body><h3>Welcome ' + request.auth.credentials.name + '!</h3><br/><form method="get" action="/logout"><input type="submit" value="Logout"></form></body></html>');
this.reply('<html><head><title>Login page</title></head><body><h3>Welcome ' + this.auth.credentials.name + '!</h3><br/><form method="get" action="/logout"><input type="submit" value="Logout"></form></body></html>');
};


internals.login = function (request) {
internals.login = function () {

if (request.auth.isAuthenticated) {
return request.reply.redirect('/');
if (this.auth.isAuthenticated) {
return this.reply.redirect('/');
}

var message = '';
var account = null;

if (request.method === 'post') {
if (this.method === 'post') {

if (!request.payload.username ||
!request.payload.password) {
if (!this.payload.username ||
!this.payload.password) {

message = 'Missing username or password';
}
else {
account = internals.users[request.payload.username];
account = internals.users[this.payload.username];
if (!account ||
account.password !== request.payload.password) {
account.password !== this.payload.password) {

message = 'Invalid username or password';
}
}
}

if (request.method === 'get' ||
if (this.method === 'get' ||
message) {

return request.reply('<html><head><title>Login page</title></head><body>' + (message ? '<h3>' + message + '</h3><br/>' : '') + '<form method="post" action="/login">Username: <input type="text" name="username"><br>Password: <input type="password" name="password"><br/><input type="submit" value="Login"></form></body></html>');
return this.reply('<html><head><title>Login page</title></head><body>' + (message ? '<h3>' + message + '</h3><br/>' : '') + '<form method="post" action="/login">Username: <input type="text" name="username"><br>Password: <input type="password" name="password"><br/><input type="submit" value="Login"></form></body></html>');
}

request.auth.session.set(account);
return request.reply.redirect('/');
this.auth.session.set(account);
return this.reply.redirect('/');
};


internals.logout = function (request) {
internals.logout = function () {

request.auth.session.clear();
return request.reply.redirect('/');
this.auth.session.clear();
return this.reply.redirect('/');
};


Expand All @@ -83,8 +83,7 @@ internals.main = function () {

http.route([
{ method: 'GET', path: '/', config: { handler: internals.home, auth: true } },
{ method: 'GET', path: '/login', config: { handler: internals.login, auth: { mode: 'try' } } },
{ method: 'POST', path: '/login', config: { handler: internals.login, auth: { mode: 'try' } } },
{ method: '*', path: '/login', config: { handler: internals.login, auth: { mode: 'try' } } },
{ method: 'GET', path: '/logout', config: { handler: internals.logout, auth: true } }
]);

Expand Down
4 changes: 2 additions & 2 deletions lib/payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ exports.read = function (request, next) {

// Levels are: 'stream', 'raw', 'parse'

var level = request.route.payload;
var level = request.route.payload || (request.route.validate.payload || request.method === 'post' || request.method === 'put' ? 'parse' : 'stream');
if (level === 'stream') {
return next();
}
Expand Down Expand Up @@ -125,7 +125,7 @@ exports.read = function (request, next) {

var parse = function (payload) {

request.rawPayload = (payload.length ? payload : null);
request.rawPayload = payload;

if (level !== 'parse') { // 'raw'
return finish();
Expand Down
35 changes: 18 additions & 17 deletions lib/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ internals.Proxy.prototype.handler = function () {

var isGet = (request.method === 'get' || request.method === 'head');

// Parsed payload interface

if (self.settings.isCustomPostResponse || // Custom response method
(isGet && request.route.cache.mode.server)) { // GET/HEAD with Cache

// Callback interface

delete options.headers['accept-encoding']; // Remove until Request supports unzip/deflate
self.httpClient(options, function (err, res, payload) {

Expand All @@ -85,29 +85,30 @@ internals.Proxy.prototype.handler = function () {

return self.settings.postResponse(request, self.settings, res, payload);
});

return;
}
else {

// Stream interface
// Streamed payload interface

if (!isGet &&
request.rawPayload) {
if (!isGet &&
request.rawPayload &&
request.rawPayload.length) {

options.headers['Content-Type'] = req.headers['content-type'];
options.body = request.rawPayload;
}
options.headers['Content-Type'] = req.headers['content-type'];
options.body = request.rawPayload;
}

var reqStream = self.httpClient(options);
reqStream.on('response', function (resStream) {
var reqStream = self.httpClient(options);
reqStream.on('response', function (resStream) {

request.reply(resStream); // Request._respond will pass-through headers and status code
});
request.reply(resStream); // Request._respond will pass-through headers and status code
});

if (!isGet &&
request.route.payload === 'stream') {
if (!isGet &&
!request.rawPayload) {

request.raw.req.pipe(reqStream);
}
request.raw.req.pipe(reqStream);
}
});
};
Expand Down
4 changes: 0 additions & 4 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ exports = module.exports = internals.Route = function (options, server, env) {

this.settings.validate = this.settings.validate || {};
Utils.assert(!this.settings.validate.payload || !this.settings.payload || this.settings.payload === 'parse', 'Route payload must be set to \'parse\' when payload validation enabled');

this.settings.payload = this.settings.payload ||
(this.settings.validate.payload || this.method === 'post' || this.method === 'put' ? 'parse' : 'stream');

Utils.assert(!this.settings.jsonp || typeof this.settings.jsonp === 'string', 'Bad route JSONP parameter name');

// Authentication configuration
Expand Down
15 changes: 13 additions & 2 deletions test/integration/payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ describe('Payload', function () {

var server = new Hapi.Server('localhost', 0, { timeout: { client: 50 } });
server.route({ method: 'POST', path: '/', config: { handler: handler, payload: 'parse' } });
server.route({ method: '*', path: '/any', handler: handler });

before(function (done) {

Expand All @@ -324,6 +325,16 @@ describe('Payload', function () {
this.push(null);
};

it('sets parse mode when route methos is * and request is POST or PUT', function (done) {

server.inject({ url: '/any', method: 'POST', headers: { 'Content-Type': 'application/json' }, payload: '{ "key": "09876" }' }, function (res) {

expect(res.statusCode).to.equal(200);
expect(res.result).to.equal('09876');
done();
});
});

it('sets the request payload with the streaming data', function (done) {

var options = {
Expand Down Expand Up @@ -461,7 +472,7 @@ describe('Payload', function () {

var handler = function () {

this.reply('Success');
this.reply('Success');
};

var server = new Hapi.Server();
Expand Down Expand Up @@ -547,7 +558,7 @@ describe('Payload', function () {
var stats = Fs.statSync(path);
var fileStream = Fs.createReadStream(path);
var fileContents = Fs.readFileSync(path, { encoding: 'binary' });

var fileHandler = function (request) {

expect(request.raw.req.headers['content-type']).to.contain('multipart/form-data');
Expand Down

0 comments on commit f710547

Please sign in to comment.