Permalink
Browse files

add res.redirect support

closes #5
  • Loading branch information...
1 parent df32f6c commit 3a50f0312b554e52625adf5a38b7e621d6cecdd9 @aheckmann aheckmann committed Feb 29, 2012
Showing with 163 additions and 8 deletions.
  1. +43 −4 index.js
  2. +120 −4 test/index.js
View
@@ -112,14 +112,13 @@ function resolve (options, callback, nested) {
* Add Promise/Query support to res.send.
*/
-var oldsend = res.send;
-
+var send = res.send;
res.send = function (body, headers, status) {
var self = this;
function handleResult (err, result) {
if (err) return self.req.next(err);
- oldsend.call(self, result, headers, status);
+ send.call(self, result, headers, status);
}
if (body instanceof Promise) {
@@ -134,5 +133,45 @@ res.send = function (body, headers, status) {
return resolve(body, handleResult);
}
- oldsend.call(this, body, headers, status);
+ send.call(this, body, headers, status);
};
+
+/**
+ * Extends res.redirect with mongoose Promise support.
+ *
+ * Does not accept Queries since those return documents.
+ * Instead, manually handle the result of your query first,
+ * then resolve your promise with the url and optional status.
+ *
+ * var promise = new mongoose.Promise;
+ * res.redirect(promise);
+ *
+ * // later...
+ * promise.complete(url [, status]);
+ *
+ * The promise can pass an optional status code as the
+ * second argument.
+ *
+ * promise.complete('/elsewhere', 301);
+ */
+
+var redirect = res.redirect;
+res.redirect = function (url, status) {
+ var self = this;
+
+ function handleResult (err, result, code) {
+ if (err) return self.req.next(err);
+
+ if ('string' != typeof result) {
+ return self.req.next(new Error('URL Expected'));
+ }
+
+ redirect.call(self, result, code || status);
+ }
+
+ if (url instanceof Promise) {
+ return url.addBack(handleResult);
+ }
+
+ redirect.call(this, url, status);
+}
View
@@ -51,6 +51,15 @@ DrumsetSchema.statics.promiseError = function () {
return promise;
}
+DrumsetSchema.statics.usePromiseRedirect = function (status) {
+ var url = '/promise/redirect';
+ var promise = new Promise;
+ process.nextTick(function () {
+ promise.complete(url, status);
+ });
+ return promise;
+}
+
mongoose.model('Drumset', DrumsetSchema);
/**
@@ -126,12 +135,14 @@ function assignExports () {
* Clean up the test db when finished.
*/
- var testsrunning = 3;
+ var testsrunning = 4;
function finishTest () {
if (--testsrunning) return;
var db = connect();
- db.db.dropDatabase(function () {
- db.close();
+ db.once('open', function () {
+ db.db.dropDatabase(function () {
+ db.close();
+ });
});
}
@@ -553,6 +564,111 @@ function assignExports () {
assert.ok(~res.body.indexOf("Error: splat!"));
}
);
- }
+ };
+
+ exports.redirect = function () {
+ var app = makeapp();
+ var db = connect();
+ var Drumset = db.model('Drumset', collection);
+
+ app.get('/redirect', function (req, res) {
+ res.redirect('/sound');
+ });
+
+ app.get('/redirect/status', function (req, res) {
+ res.redirect('/sound', 301);
+ });
+
+ app.get('/redirectpromise', function (req, res) {
+ res.redirect(Drumset.usePromiseRedirect());
+ });
+
+ app.get('/redirectpromise/status', function (req, res) {
+ res.redirect(Drumset.usePromiseRedirect(), 301);
+ });
+
+ app.get('/redirectpromisestatus', function (req, res) {
+ res.redirect(Drumset.usePromiseRedirect(301));
+ });
+
+ app.get('/redirectpromisestatus/override', function (req, res) {
+ res.redirect(Drumset.usePromiseRedirect(301), 500);
+ });
+
+ app.get('/redirectpromiseerror', function (req, res) {
+ res.redirect(Drumset.promiseError());
+ });
+
+ // test
+
+ var pending = 7;
+ function done () {
+ if (--pending) return;
+ db.close();
+ finishTest();
+ }
+
+ assert.response(app,
+ { url: '/redirect' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 302);
+ assert.ok('/sound', res.headers['Location']);
+ }
+ );
+
+ assert.response(app,
+ { url: '/redirect/status' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 301);
+ assert.ok('/sound', res.headers['Location']);
+ }
+ );
+
+ assert.response(app,
+ { url: '/redirectpromise' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 302);
+ assert.ok('/redirect/promise', res.headers['Location']);
+ }
+ );
+
+ assert.response(app,
+ { url: '/redirectpromise/status' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 301);
+ assert.ok('/redirect/promise', res.headers['Location']);
+ }
+ );
+ assert.response(app,
+ { url: '/redirectpromisestatus' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 301);
+ assert.ok('/redirect/promise', res.headers['Location']);
+ }
+ );
+
+ assert.response(app,
+ { url: '/redirectpromisestatus/override' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 301);
+ assert.ok('/redirect/promise', res.headers['Location']);
+ }
+ );
+
+ assert.response(app,
+ { url: '/redirectpromiseerror' }
+ , function (res) {
+ done();
+ assert.equal(res.statusCode, 500);
+ assert.ok(/splat!/.test(res.body));
+ }
+ );
+ }
}

0 comments on commit 3a50f03

Please sign in to comment.