Skip to content

Commit 26df1c0

Browse files
authored
Merge pull request #24 from dollarshaveclub/middleware-hooks
Middleware hooks
2 parents 80ac9a7 + d5e5a80 commit 26df1c0

File tree

14 files changed

+84228
-13
lines changed

14 files changed

+84228
-13
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ let server = new FastBootAppServer({
103103
server.start();
104104
```
105105

106+
## Pre and Post FastBoot middleware hooks
107+
108+
If you need something less than a custom server and just want to run some middleware
109+
before or after FastBoot runs, the server provides hooks for you to do so:
110+
111+
```js
112+
// Custom Middlewares
113+
function modifyRequest(req, res, next) { /* do pre-fastboot stuff to `req` */ };
114+
function handleErrors(err, req, res, next) { /* do error recovery stuff */ };
115+
116+
const server = FastBootAppServer({
117+
beforeMiddleware: function (app) { app.use(modifyRequest); },
118+
afterMiddleware: function (app) { app.use(handleErrors); }
119+
})
120+
```
121+
106122
## Downloaders
107123

108124
You can point the app server at a static path that you manage, but that
@@ -191,7 +207,7 @@ following interface:
191207

192208
#### `subscribe(notify)`
193209

194-
The `subscribe()` method ony our notifier is passed a `notify` function.
210+
The `subscribe()` method on your notifier is passed a `notify` function.
195211
If you detect that a new version of your app has been deployed (whether
196212
via polling or a push notification), call this function to trigger a
197213
reload.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"compression": "^1.6.2",
3030
"express": "^4.13.3",
3131
"fastboot": "^1.0.0-rc.0",
32-
"fastboot-express-middleware": "^1.0.0-rc.3",
32+
"fastboot-express-middleware": "^1.0.0-rc.4",
3333
"fs-promise": "^0.3.1"
3434
},
3535
"devDependencies": {

src/express-http-server.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
const express = require('express');
44
const basicAuth = require('./basic-auth');
55

6+
function noop() {}
7+
68
class ExpressHTTPServer {
79
constructor(options) {
810
options = options || {};
@@ -13,18 +15,23 @@ class ExpressHTTPServer {
1315
this.password = options.password;
1416
this.cache = options.cache;
1517
this.gzip = options.gzip || false;
18+
this.beforeMiddleware = options.beforeMiddleware || noop;
19+
this.afterMiddleware = options.afterMiddleware || noop;
1620

1721
this.app = express();
18-
if (options.gzip) {
19-
this.app.use(require('compression')());
20-
}
2122
}
2223

23-
serve(middleware) {
24+
serve(fastbootMiddleware) {
2425
let app = this.app;
2526
let username = this.username;
2627
let password = this.password;
2728

29+
this.beforeMiddleware(app);
30+
31+
if (this.gzip) {
32+
this.app.use(require('compression')());
33+
}
34+
2835
if (username !== undefined || password !== undefined) {
2936
this.ui.writeLine(`adding basic auth; username=${username}; password=${password}`);
3037
app.use(basicAuth(username, password));
@@ -35,14 +42,16 @@ class ExpressHTTPServer {
3542
}
3643

3744
if (this.distPath) {
38-
app.get('/', middleware);
45+
app.get('/', fastbootMiddleware);
3946
app.use(express.static(this.distPath));
4047
app.get('/assets/*', function(req, res) {
4148
res.sendStatus(404);
4249
});
4350
}
4451

45-
app.get('/*', middleware);
52+
app.get('/*', fastbootMiddleware);
53+
54+
this.afterMiddleware(app);
4655

4756
return new Promise(resolve => {
4857
let listener = app.listen(process.env.PORT || 3000, () => {

src/fastboot-app-server.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ class FastBootAppServer {
1515
this.notifier = options.notifier;
1616
this.cache = options.cache;
1717
this.ui = options.ui;
18-
this.gzip = options.gzip || false;
18+
this.gzip = options.gzip;
1919
this.httpServer = options.httpServer;
20+
this.beforeMiddleware = options.beforeMiddleware;
21+
this.afterMiddleware = options.afterMiddleware;
2022

2123
if (!this.ui) {
2224
let UI = require('./ui');
@@ -31,7 +33,9 @@ class FastBootAppServer {
3133
distPath: this.distPath || process.env.FASTBOOT_DIST_PATH,
3234
cache: this.cache,
3335
gzip: this.gzip,
34-
httpServer: this.httpServer
36+
httpServer: this.httpServer,
37+
beforeMiddleware: this.beforeMiddleware,
38+
afterMiddleware: this.afterMiddleware
3539
});
3640

3741
this.worker.start();

src/worker.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ class Worker {
1010
this.httpServer = options.httpServer;
1111
this.ui = options.ui;
1212
this.cache = options.cache;
13-
this.gzip = options.gzip || false;
13+
this.gzip = options.gzip;
14+
this.beforeMiddleware = options.beforeMiddleware;
15+
this.afterMiddleware = options.afterMiddleware;
1416

1517
if (!this.httpServer) {
1618
this.httpServer = new ExpressHTTPServer({
1719
ui: this.ui,
1820
distPath: this.distPath,
1921
cache: this.cache,
20-
gzip: this.gzip
22+
gzip: this.gzip,
23+
beforeMiddleware: this.beforeMiddleware,
24+
afterMiddleware: this.afterMiddleware,
2125
});
2226
}
2327

@@ -58,7 +62,6 @@ class Worker {
5862
buildMiddleware() {
5963
this.fastboot = new FastBoot({
6064
distPath: this.distPath,
61-
resilient: true
6265
});
6366

6467
return fastbootMiddleware({

test/app-server-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,25 @@ describe("FastBootAppServer", function() {
7070
});
7171
});
7272

73+
it("executes beforeMiddleware", function() {
74+
return runServer('before-middleware-server')
75+
.then(() => request('http://localhost:3000'))
76+
.then(response => {
77+
expect(response.statusCode).to.equal(418);
78+
expect(response.headers['x-test-header']).to.equal('testing');
79+
expect(response.body).to.equal(JSON.stringify({ send: 'json back'}));
80+
});
81+
});
82+
83+
it("executes afterMiddleware when there is an error", function() {
84+
return runServer('after-middleware-server')
85+
.then(() => request('http://localhost:3000'))
86+
.then(response => {
87+
expect(response.body).to.not.match(/error/);
88+
expect(response.headers['x-test-header']).to.equal('testing');
89+
})
90+
});
91+
7392
});
7493

7594
function runServer(name) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
var alchemistRequire = require('broccoli-module-alchemist/require');
5+
var FastBootAppServer = alchemistRequire('fastboot-app-server');
6+
7+
function setXTestHeader(err, req, res, next) {
8+
res.set('x-test-header', 'testing')
9+
next();
10+
}
11+
12+
var server = new FastBootAppServer({
13+
distPath: path.resolve(__dirname, './broken-app'),
14+
afterMiddleware: function (app) {
15+
app.use(setXTestHeader);
16+
},
17+
resilient: true,
18+
});
19+
20+
server.start();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
var alchemistRequire = require('broccoli-module-alchemist/require');
5+
var FastBootAppServer = alchemistRequire('fastboot-app-server');
6+
7+
function setStatusCode418(req, res, next) {
8+
res.status(418);
9+
next();
10+
}
11+
12+
function setXTestHeader(req, res, next) {
13+
res.set('X-Test-Header', 'testing')
14+
next();
15+
}
16+
17+
function sendJsonAndTerminate(req, res, next) {
18+
res.json({ send: 'json back' });
19+
res.send();
20+
}
21+
22+
var server = new FastBootAppServer({
23+
distPath: path.resolve(__dirname, './basic-app'),
24+
beforeMiddleware: function (app) {
25+
app.use(setStatusCode418);
26+
app.use(setXTestHeader);
27+
app.use(sendJsonAndTerminate);
28+
}
29+
});
30+
31+
server.start();

0 commit comments

Comments
 (0)