Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Explicit proxies #1530

Merged
merged 10 commits into from
Aug 7, 2014
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ember-cli Changelog

* [ENHANCEMENT] adds http-proxy for explicit, multi proxy use[#1474](https://github.com/stefanpenner/ember-cli/pull/1530)
* [BREAKING ENHANCEMENT] renames apiStub to http-mock to match other http-related generators [#1474] (https://github.com/stefanpenner/ember-cli/pull/1530)
* [ENHANCEMENT] Log proxy server traffic when using `ember serve --proxy` [#1583](https://github.com/stefanpenner/ember-cli/pull/1583)
* [ENHANCEMENT] Remove chain from express server [#1474](https://github.com/stefanpenner/ember-cli/pull/1474)
* [ENHANCEMENT] Remove Blueprint lookup failure stacktrace [#1476](https://github.com/stefanpenner/ember-cli/pull/1476)
Expand Down
21 changes: 0 additions & 21 deletions blueprints/api-stub/files/server/index.js

This file was deleted.

29 changes: 29 additions & 0 deletions blueprints/http-mock/files/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// To use it create some files under `routes/`
// e.g. `server/routes/ember-hamsters.js`
//
// module.exports = function(app) {
// app.get('/ember-hamsters', function(req, res) {
// res.send('hello');
// });
// };

var bodyParser = require('body-parser');
var globSync = require('glob').sync;
var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);

module.exports = function(app) {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));

mocks.forEach(function(route) { route(app)});

// proxy expects a stream, but express will have turned
// the request stream into an object because bodyParser
// has run. We have to convert it back to stream:
// https://github.com/nodejitsu/node-http-proxy/issues/180
app.use(require('connect-restreamer')());
proxies.forEach(function(route) { route(app)});
};
File renamed without changes.
3 changes: 3 additions & 0 deletions blueprints/http-proxy/files/server/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"node": true
}
29 changes: 29 additions & 0 deletions blueprints/http-proxy/files/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// To use it create some files under `routes/`
// e.g. `server/routes/ember-hamsters.js`
//
// module.exports = function(app) {
// app.get('/ember-hamsters', function(req, res) {
// res.send('hello');
// });
// };

var bodyParser = require('body-parser');
var globSync = require('glob').sync;
var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);

module.exports = function(app) {
app.use(bodyParser.json());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the bodyParser was giving proxy users trouble

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you remember what kind of troubles? We were able to successfully proxy, but we're also using json. Was it proxying to non-json that was problematic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm found it #925

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using body parser caused post and put requests to fail, IIRC.

app.use(bodyParser.urlencoded({
extended: true
}));

mocks.forEach(function(route) { route(app)});

// proxy expects a stream, but express will have turned
// the request stream into an object because bodyParser
// has run. We have to convert it back to stream:
// https://github.com/nodejitsu/node-http-proxy/issues/180
app.use(require('connect-restreamer')());
proxies.forEach(function(route) { route(app)});
};
14 changes: 14 additions & 0 deletions blueprints/http-proxy/files/server/proxies/__name__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var Proxy = require('http-proxy');

// For options, see:
// https://github.com/nodejitsu/node-http-proxy
var proxy = Proxy.createProxyServer({});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


module.exports = function(app) {

app.use('/<%=camelizedModuleName %>', function(req, res, next){
proxy.web(req, res, { target: '<%=proxyUrl %>' });
})

};

11 changes: 11 additions & 0 deletions blueprints/http-proxy/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var Blueprint = require('../../lib/models/blueprint');

module.exports = Blueprint.extend({
locals: function(options) {
var proxyUrl = options.args[2];
return {
path: '/' + options.entity.name.replace(/^\//, ''),
proxyUrl: proxyUrl
};
}
});
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@
"tiny-lr": "0.0.9",
"tmp-sync": "^1.0.1",
"walk-sync": "^0.1.2",
"yam": "0.0.12"
"yam": "0.0.12",
"http-proxy": "^1.1.6",
"connect-restreamer": "^1.0.0"
},
"devDependencies": {
"chai": "^1.9.1",
Expand Down
18 changes: 15 additions & 3 deletions tests/acceptance/destroy-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,17 +429,29 @@ describe('Acceptance: ember destroy', function() {
return assertDestroyAfterGenerate(commandArgs, files);
});

it('api-stub foo', function() {
var commandArgs = ['api-stub', 'foo'];
it('http-mock foo', function() {
var commandArgs = ['http-mock', 'foo'];
var files = [
'server/index.js',
'server/routes/foo.js',
'server/mocks/foo.js',
'server/.jshintrc'
];

return assertDestroyAfterGenerate(commandArgs, files);
});

it('http-proxy foo', function() {
var commandArgs = ['http-proxy', 'foo'];
var files = [
'server/index.js',
'server/proxies/foo.js',
'server/.jshintrc'
];

return assertDestroyAfterGenerate(commandArgs, files);
});


it('acceptance-test foo', function() {
var commandArgs = ['acceptance-test', 'foo'];
var files = ['tests/acceptance/foo-test.js'];
Expand Down
69 changes: 61 additions & 8 deletions tests/acceptance/generate-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -694,30 +694,38 @@ describe('Acceptance: ember generate', function() {
});
});

it('api-stub foo', function() {
return generate(['api-stub', 'foo']).then(function() {
it('http-mock foo', function() {
return generate(['http-mock', 'foo']).then(function() {
assertFile('server/index.js', {
contains: "var bodyParser = require('body-parser');" + EOL +
"var globSync = require('glob').sync;" + EOL +
"var routes = globSync('./routes/**/*.js', { cwd: __dirname }).map(require);" + EOL +
EOL +
"var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);" + EOL +
"var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);" + EOL +
"" + EOL +
"module.exports = function(app) {" + EOL +
" app.use(bodyParser.json());" + EOL +
" app.use(bodyParser.urlencoded({" + EOL +
" extended: true" + EOL +
" }));" + EOL +
EOL +
" routes.forEach(function(route) { route(app); });" + EOL +
"" + EOL +
" mocks.forEach(function(route) { route(app)});" + EOL +
"" + EOL +
" // proxy expects a stream, but express will have turned" + EOL +
" // the request stream into an object because bodyParser" + EOL +
" // has run. We have to convert it back to stream:" + EOL +
" // https://github.com/nodejitsu/node-http-proxy/issues/180" + EOL +
" app.use(require('connect-restreamer')());" + EOL +
" proxies.forEach(function(route) { route(app)});" + EOL +
"};"
});
assertFile('server/routes/foo.js', {
assertFile('server/mocks/foo.js', {
contains: "module.exports = function(app) {" + EOL +
" var express = require('express');" + EOL +
" var fooRouter = express.Router();" + EOL +
" fooRouter.get('/', function(req, res) {" + EOL +
" res.send({foo:[]});" + EOL +
" });" + EOL +
" app.use('/api/foo', fooRouter);" + EOL + "" +
" app.use('/api/foo', fooRouter);" + EOL +
"};"
});
assertFile('server/.jshintrc', {
Expand All @@ -726,6 +734,51 @@ describe('Acceptance: ember generate', function() {
});
});

it('http-proxy foo', function() {
return generate(['http-proxy', 'foo', 'http://localhost:5000']).then(function() {
assertFile('server/index.js', {
contains: "var bodyParser = require('body-parser');\n" +
"var globSync = require('glob').sync;\n" +
"var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);\n" +
"var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);\n" +
"\n" +
"module.exports = function(app) {\n" +
" app.use(bodyParser.json());\n" +
" app.use(bodyParser.urlencoded({\n" +
" extended: true\n" +
" }));\n" +
"\n" +
" mocks.forEach(function(route) { route(app)});\n" +
"\n" +
" // proxy expects a stream, but express will have turned\n" +
" // the request stream into an object because bodyParser\n" +
" // has run. We have to convert it back to stream:\n" +
" // https://github.com/nodejitsu/node-http-proxy/issues/180\n" +
" app.use(require('connect-restreamer')());\n" +
" proxies.forEach(function(route) { route(app)});\n" +
"};"
});
assertFile('server/proxies/foo.js', {
contains: "var Proxy = require('http-proxy');\n" +
"\n" +
"// For options, see:\n" +
"// https://github.com/nodejitsu/node-http-proxy\n" +
"var proxy = Proxy.createProxyServer({});\n" +
"\n" +
"module.exports = function(app) {\n" +
"\n" +
" app.use('/foo', function(req, res, next){\n" +
" proxy.web(req, res, { target: 'http://localhost:5000' });\n" +
" })\n" +
"\n" +
"};"
});
assertFile('server/.jshintrc', {
contains: '{\n "node": true\n}'
});
});
});

it('uses blueprints from the project directory', function() {
return initApp()
.then(function() {
Expand Down
3 changes: 2 additions & 1 deletion tests/acceptance/help-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ describe('Acceptance: ember help', function() {
assert.include(output, 'ember-cli commands:');
assert.include(output, ' app');
assert.include(output, ' adapter');
assert.include(output, ' api');
assert.include(output, ' http-mock');
assert.include(output, ' http-proxy');
assert.include(output, ' app');
assert.include(output, ' blueprint');
assert.include(output, ' component');
Expand Down