Skip to content
This repository has been archived by the owner on May 17, 2019. It is now read-only.

Commit

Permalink
Use end event rather than overwriting ctx.res.end (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
ganemone authored Aug 30, 2018
1 parent 4e4601c commit 7f40e52
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 14 deletions.
51 changes: 51 additions & 0 deletions src/__tests__/express-send.node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/** Copyright (c) 2018 Uber Technologies, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import test from 'tape-cup';
import App from 'fusion-core';
import express from 'express';
import {HttpHandlerToken} from '../tokens.js';
import HttpHandlerPlugin from '../server.js';
import {startServer} from '../test-util.js';

test('http handler with express using send', async t => {
const app = new App('test', () => 'test');
app.register(HttpHandlerPlugin);
const expressApp = express();
expressApp.get('/express', (req, res) => {
res.send('OK');
});
app.register(HttpHandlerToken, expressApp);
app.middleware((ctx, next) => {
if (ctx.url === '/express') {
t.equal(ctx.res.statusCode, 200, 'express route sets status code');
} else {
t.equal(ctx.res.statusCode, 404, 'non express routes default to 404');
}
// $FlowFixMe
ctx.req.secure = false;
ctx.body = 'hit fallthrough';
return next();
});

const {server, request} = await startServer(app.callback());

t.equal(await request('/express'), 'OK', 'express routes can send responses');
t.equal(
await request('/fallthrough'),
'hit fallthrough',
'express routes can delegate back to koa'
);
t.equal(
await request('/fallthrough'),
'hit fallthrough',
'express routes can delegate back to koa'
);
server.close();
t.end();
});
41 changes: 27 additions & 14 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
/* eslint-env node */

import {createPlugin} from 'fusion-core';
import {HttpHandlerToken} from './tokens.js';

import type {FusionPlugin} from 'fusion-core';

import {HttpHandlerToken} from './tokens.js';
import type {DepsType, ServiceType} from './types.js';

const plugin =
Expand All @@ -29,23 +27,38 @@ const plugin =
return next();
}
return new Promise((resolve, reject) => {
const oldEnd = ctx.res.end.bind(ctx.res);
// $FlowFixMe
ctx.res.end = (data, encoding, cb) => {
const {req, res} = ctx;
// Default http response object behavior defaults res.statusCode to 200. Koa sets it to 404.
// This allows for http servers to use `end()` or express to use `send()` without specifying a 200 status code
const prevStatusCode = ctx.res.statusCode;
ctx.res.statusCode = 200;
const listener = () => {
ctx.respond = false;
return next()
.then(resolve)
.then(() => {
oldEnd(data, encoding, cb);
});
return done();
};
handler(ctx.req, ctx.res, () => {
res.on('end', listener);
res.on('finish', listener);

handler(req, res, () => {
ctx.res.statusCode = prevStatusCode;
return done();
});

function done() {
// Express mutates the req object to make this property non-writable.
// We need to make it writable because other plugins (like koa-helmet) will set it
// $FlowFixMe
ctx.res.end = oldEnd;
Object.defineProperty(req, 'secure', {
// $FlowFixMe
value: req.secure,
writable: true,
});
res.removeListener('end', listener);
res.removeListener('finish', listener);
return next()
.then(resolve)
.catch(reject);
});
}
});
};
},
Expand Down

0 comments on commit 7f40e52

Please sign in to comment.