diff --git a/addon/ng2/commands/serve.ts b/addon/ng2/commands/serve.ts index 7834298335ff..c23ae850ad85 100644 --- a/addon/ng2/commands/serve.ts +++ b/addon/ng2/commands/serve.ts @@ -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; @@ -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' }, diff --git a/addon/ng2/tasks/serve-webpack.ts b/addon/ng2/tasks/serve-webpack.ts index f8e74662d785..1eb7de193478 100644 --- a/addon/ng2/tasks/serve-webpack.ts +++ b/addon/ng2/tasks/serve-webpack.ts @@ -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'; @@ -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*`); diff --git a/tests/e2e/e2e_workflow.spec.js b/tests/e2e/e2e_workflow.spec.js index 0ec50afe5d0f..cf00746044d1 100644 --- a/tests/e2e/e2e_workflow.spec.js +++ b/tests/e2e/e2e_workflow.spec.js @@ -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 { @@ -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() {