From 69cbb63cc81942884207a8e03969e27f6a44dbf8 Mon Sep 17 00:00:00 2001 From: "yuhao.ju" Date: Tue, 11 Apr 2017 12:00:18 +0800 Subject: [PATCH] feat(server): add http-proxy-middleware to handle server proxy --- lib/commands/server.js | 40 +++++++++++++++++++++++++++++++++++++--- lib/models/Project.js | 6 ++++++ package.json | 1 + src/commands/server.js | 40 +++++++++++++++++++++++++++++++++++++--- src/models/Project.js | 5 +++++ yarn.lock | 28 ++++++++++++++++++++++++++-- 6 files changed, 112 insertions(+), 8 deletions(-) diff --git a/lib/commands/server.js b/lib/commands/server.js index 46d2b5f..7f48699 100644 --- a/lib/commands/server.js +++ b/lib/commands/server.js @@ -17,7 +17,8 @@ var connect = require('connect'), requireg = require('requireg'), logSymbols = require('log-symbols'), favicon = require('serve-favicon'), - webpackDevMiddleware = require('webpack-dev-middleware'); + webpackDevMiddleware = require('webpack-dev-middleware'), + httpProxy = require('http-proxy-middleware'); var Manager = require('../modules/manager.js'); var UtilFs = require('../utils/fs.js'); @@ -73,6 +74,40 @@ exports.run = function (options) { }); } + // proxy + var currentProxy = []; + app.use(function (req, res, next) { + try { + var projectInfo = getProjectInfo(req); + var project = Manager.getProject(projectInfo.projectCwd, { cache: false }); + + if (project.proxy && project.proxy.length !== currentProxy.length && project.proxy[0] !== currentProxy[0]) { + currentProxy = project.proxy; + currentProxy.map(function (proxyItem) { + // hacky way to add middleware + if (typeof proxyItem === 'string') { + app.stack.unshift({ + route: '', handle: httpProxy(proxyItem) + }); + } else { + if ((typeof proxyItem === 'undefined' ? 'undefined' : _typeof(proxyItem)) !== 'object' || !proxyItem.route || !proxyItem.options) { + logWarn('Not valid proxy: ' + JSON.stringify(proxyItem)); + } else { + app.stack.unshift({ + route: proxyItem.route, handle: httpProxy(proxyItem.options) + }); + } + } + }); + } + } catch (e) { + logError(e); + } + + next(); + }); + + // a simple middleware app.use(favicon(sysPath.join(__dirname, '../../static/imgs/favicon.ico'))); // 预处理 @@ -432,8 +467,7 @@ exports.run = function (options) { redirect: false, index: false })); - - app.use(serveIndex(cwd)); + app.use(serveIndex(cwd, { icons: true })); // 启动 http server 和 https server(如果有) var servers = []; diff --git a/lib/models/Project.js b/lib/models/Project.js index 9517315..1ede3d0 100644 --- a/lib/models/Project.js +++ b/lib/models/Project.js @@ -94,6 +94,11 @@ var Project = function () { }); } } + }, { + key: 'setProxy', + value: function setProxy(proxy) { + this.proxy = proxy || []; + } }, { key: 'readConfig', value: function readConfig() { @@ -202,6 +207,7 @@ var Project = function () { handleExportsConfig.bind(this)(ykitConfigFile.config); this.setCommands(ykitConfigFile.commands || ykitConfigFile.config.command); // 后者兼容以前形式 this.setHooks(ykitConfigFile.hooks); + this.setProxy(ykitConfigFile.proxy); } else { logError('Local ' + this.configFile + ' config not found.'); logDoc('http://ued.qunar.com/ykit/docs-配置.html'); diff --git a/package.json b/package.json index 4f6ca9a..6f407c5 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "fs-extra": "^1.0.0", "globby": "^5.0.0", "html-loader": "^0.4.3", + "http-proxy-middleware": "^0.17.4", "jerryproxy": "1.0.91", "js-yaml": "^3.6.1", "json-loader": "^0.5.4", diff --git a/src/commands/server.js b/src/commands/server.js index a5def09..6f71d18 100644 --- a/src/commands/server.js +++ b/src/commands/server.js @@ -13,7 +13,8 @@ const connect = require('connect'), requireg = require('requireg'), logSymbols = require('log-symbols'), favicon = require('serve-favicon'), - webpackDevMiddleware = require('webpack-dev-middleware'); + webpackDevMiddleware = require('webpack-dev-middleware'), + httpProxy = require('http-proxy-middleware'); const Manager = require('../modules/manager.js'); const UtilFs = require('../utils/fs.js'); @@ -67,6 +68,40 @@ exports.run = (options) => { }); } + // proxy + let currentProxy = []; + app.use(function (req, res, next) { + try { + const projectInfo = getProjectInfo(req); + const project = Manager.getProject(projectInfo.projectCwd, { cache: false }); + + if(project.proxy && project.proxy.length !== currentProxy.length && project.proxy[0] !== currentProxy[0]) { + currentProxy = project.proxy; + currentProxy.map((proxyItem) => { + // hacky way to add middleware + if(typeof proxyItem === 'string') { + app.stack.unshift({ + route: '', handle: httpProxy(proxyItem) + }); + } else { + if(typeof proxyItem !== 'object' || !proxyItem.route || !proxyItem.options) { + logWarn('Not valid proxy: ' + JSON.stringify(proxyItem)); + } else { + app.stack.unshift({ + route: proxyItem.route, handle: httpProxy(proxyItem.options) + }); + } + } + }); + } + } catch (e) { + logError(e); + } + + next(); + }); + + // a simple middleware app.use(favicon(sysPath.join(__dirname, '../../static/imgs/favicon.ico'))); // 预处理 @@ -432,8 +467,7 @@ exports.run = (options) => { redirect: false, index: false })); - - app.use(serveIndex(cwd)); + app.use(serveIndex(cwd, {icons: true})); // 启动 http server 和 https server(如果有) let servers = []; diff --git a/src/models/Project.js b/src/models/Project.js index 93715ce..ddbc893 100644 --- a/src/models/Project.js +++ b/src/models/Project.js @@ -90,6 +90,10 @@ class Project { } } + setProxy(proxy) { + this.proxy = proxy || []; + } + readConfig() { if(!this.configFile) { // no local config, i.e., server command) @@ -198,6 +202,7 @@ class Project { handleExportsConfig.bind(this)(ykitConfigFile.config); this.setCommands(ykitConfigFile.commands || ykitConfigFile.config.command); // 后者兼容以前形式 this.setHooks(ykitConfigFile.hooks); + this.setProxy(ykitConfigFile.proxy); } else { logError('Local ' + this.configFile + ' config not found.'); logDoc('http://ued.qunar.com/ykit/docs-配置.html'); diff --git a/yarn.lock b/yarn.lock index 76d2a73..f1e9189 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1793,6 +1793,10 @@ event-stream@~3.3.0: stream-combiner "~0.0.4" through "~2.3.1" +eventemitter3@1.x.x: + version "1.2.0" + resolved "http://registry.npm.corp.qunar.com/eventemitter3/download/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + events@^1.0.0: version "1.1.1" resolved "http://registry.npm.corp.qunar.com/events/download/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -2570,6 +2574,22 @@ http-errors@~1.6.1: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-proxy-middleware@^0.17.4: + version "0.17.4" + resolved "http://registry.npm.corp.qunar.com/http-proxy-middleware/download/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833" + dependencies: + http-proxy "^1.16.2" + is-glob "^3.1.0" + lodash "^4.17.2" + micromatch "^2.3.11" + +http-proxy@^1.16.2: + version "1.16.2" + resolved "http://registry.npm.corp.qunar.com/http-proxy/download/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + dependencies: + eventemitter3 "1.x.x" + requires-port "1.x.x" + http-signature@~1.1.0: version "1.1.1" resolved "http://registry.npm.corp.qunar.com/http-signature/download/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -3250,7 +3270,7 @@ lodash.words@^3.0.0: dependencies: lodash._root "^3.0.0" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: version "4.17.4" resolved "http://registry.npm.corp.qunar.com/lodash/download/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -3365,7 +3385,7 @@ methods@~1.1.2: version "1.1.2" resolved "http://registry.npm.corp.qunar.com/methods/download/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micromatch@^2.1.5, micromatch@^2.3.7: +micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: version "2.3.11" resolved "http://registry.npm.corp.qunar.com/micromatch/download/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" dependencies: @@ -4468,6 +4488,10 @@ requireg@^0.1.5: rc "~1.0.0" resolve "~0.6.1" +requires-port@1.x.x: + version "1.0.0" + resolved "http://registry.npm.corp.qunar.com/requires-port/download/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + resolve-dir@^0.1.0: version "0.1.1" resolved "http://registry.npm.corp.qunar.com/resolve-dir/download/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e"