Skip to content

Support proxy to backend #1487

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

Merged
merged 12 commits into from
Aug 19, 2016
8 changes: 3 additions & 5 deletions addon/ng2/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const defaultPort = process.env.PORT || 4200;
export interface ServeTaskOptions {
port?: number;
host?: string;
proxy?: string;
insecureProxy?: boolean;
proxyConfig?: string;
watcher?: string;
liveReload?: boolean;
liveReloadHost?: string;
Expand All @@ -37,9 +36,8 @@ module.exports = Command.extend({

availableOptions: [
{ name: 'port', type: Number, default: defaultPort, aliases: ['p'] },
{ name: 'host', type: String, default: 'localhost', aliases: ['H'], description: 'Listens on localhost by default' },
{ name: 'proxy', type: String, aliases: ['pr', 'pxy'] },
{ name: 'insecure-proxy', type: Boolean, default: false, aliases: ['inspr'], description: 'Set false to proxy self-signed SSL certificates' },
{ name: 'host', type: String, default: 'localhost', aliases: ['H'], description: 'Listens on all interfaces by default' },
{ name: 'proxy-config', type: 'Path', aliases: ['pc'] },
{ name: 'watcher', type: String, default: 'events', aliases: ['w'] },
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
{ name: 'live-reload-host', type: String, aliases: ['lrh'], description: 'Defaults to host' },
Expand Down
16 changes: 15 additions & 1 deletion addon/ng2/tasks/serve-webpack.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import * as chalk from 'chalk';
import * as SilentError from 'silent-error';
import * as Task from 'ember-cli/lib/models/task';
import * as webpack from 'webpack';
import * as WebpackDevServer from 'webpack-dev-server';
Expand Down Expand Up @@ -27,11 +29,23 @@ module.exports = Task.extend({
colors: true
}));

let proxyConfig = {};
if (commandOptions.proxyConfig) {
const proxyPath = path.resolve(this.project.root, commandOptions.proxyConfig);
if (fs.existsSync(proxyPath)) {
proxyConfig = require(proxyPath);
} else {
var message = 'Proxy config file ' + proxyPath + ' does not exist.';
return Promise.reject(new SilentError(message));
}
}

const webpackDevServerConfiguration: IWebpackDevServerConfigurationOptions = {
contentBase: config.output.path,
historyApiFallback: true,
stats: webpackDevServerOutputOptions,
inline: true
inline: true,
proxy: proxyConfig
};

const serveMessage:string = chalk.green(`\n*\n*\n NG Live Development Server is running on http://${commandOptions.host}:${commandOptions.port}.\n*\n*`);
Expand Down
78 changes: 78 additions & 0 deletions tests/e2e/e2e_workflow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ var treeKill = require('tree-kill');
var child_process = require('child_process');
var ng = require('../helpers/ng');
var root = path.join(process.cwd(), 'tmp');
var express = require('express');
var http = require('http');
var request = require('request');

function existsSync(path) {
try {
Expand Down Expand Up @@ -564,6 +567,81 @@ describe('Basic end-to-end Workflow', function () {
throw new Error(msg);
});
});

it('Serve with proxy config', function () {
this.timeout(240000);
var ngServePid;
var server;

function executor(resolve, reject) {
var startedProtractor = false;
var app = express();
server = http.createServer(app);
server.listen();
app.set('port', server.address().port);

app.get('/api/test', function (req, res) {
res.send('TEST_API_RETURN');
});
var backendHost = 'localhost';
var backendPort = server.address().port

var proxyServerUrl = `http://${backendHost}:${backendPort}`;
const proxyConfigFile = path.join(process.cwd(), 'proxy.config.json');
const proxyConfig = {
'/api/*': {
target: proxyServerUrl
}
};
fs.writeFileSync(proxyConfigFile, JSON.stringify(proxyConfig, null, 2), 'utf8');
var serveProcess = child_process.exec(`${ngBin} serve --proxy-config proxy.config.json`, { maxBuffer: 500 * 1024 });
ngServePid = serveProcess.pid;

serveProcess.stdout.on('data', (data) => {
if (/webpack: bundle is now VALID/.test(data.toString('utf-8')) && !startedProtractor) {

// How to get the url with out hardcoding here?
request( 'http://localhost:4200/api/test', function(err, response, body) {
expect(response.statusCode).to.be.equal(200);
expect(body).to.be.equal('TEST_API_RETURN');
resolve();
});
}
});

serveProcess.stderr.on('data', (data) => {
reject(data);
});
serveProcess.on('close', (code) => {
code === 0 ? resolve() : reject('ng serve command closed with error')
});
}

// Need a way to close the express server
return new Promise(executor)
.then(() => {
if (ngServePid) treeKill(ngServePid);
if(server){
server.close();
}
})
.catch((msg) => {
if (ngServePid) treeKill(ngServePid);
if(server){
server.close();
}
throw new Error(msg);
});
});

it('Serve fails on invalid proxy config file', function (done) {
this.timeout(420000);
sh.exec(`${ngBin} serve --proxy-config proxy.config.does_not_exist.json`, (code) => {
expect(code).to.not.equal(0);
done();
});
});

});

function isMobileTest() {
Expand Down