Repository: ember-cli/ember-cli
Pull request #6182 (2016-08-16 13:01:39)

[BUGFIX] Allow empty string as rootURL
This enables the config parser & server to handle `rootURL` with an empty string `''`. See #6178 for details on why.

With this fix it is possible to create relative-only build products when `locationType = 'hash'`.

FYI, I have another PR pending on this, which enables the server to correctly serve this when `locationType = 'history'` by redirecting all non-root requests to the root location.


Patch:
diff --git a/lib/broccoli/ember-app.js b/lib/broccoli/ember-app.js
index 6d9182bbd..72475f4f1 100644
--- a/lib/broccoli/ember-app.js
+++ b/lib/broccoli/ember-app.js
@@ -1761,6 +1761,10 @@ function calculateBaseTag(config) {
 }
 
 function calculateRootURL(config) {
+  if (config.rootURL === '') {
+    return config.rootURL;
+  }
+
   return cleanBaseURL(config.rootURL) || '';
 }
 
diff --git a/lib/commands/serve.js b/lib/commands/serve.js
index 81e732fdc..a65e31779 100644
--- a/lib/commands/serve.js
+++ b/lib/commands/serve.js
@@ -46,11 +46,11 @@ module.exports = Command.extend({
 
         this.ui.writeDeprecateLine(
           'Using the `baseURL` setting is deprecated, use `rootURL` instead.',
-          !(!config.rootURL && config.baseURL));
+          !(!('rootURL' in config) && config.baseURL));
 
         this.ui.writeWarnLine(
           'The `baseURL` and `rootURL` settings should not be used at the same time.',
-          !(config.rootURL && config.baseURL));
+          !(('rootURL' in config) && config.baseURL));
 
         commandOptions = assign({}, commandOptions, {
           rootURL: config.rootURL,
diff --git a/lib/tasks/server/express-server.js b/lib/tasks/server/express-server.js
index 718c9a4fd..9cccb6a1f 100644
--- a/lib/tasks/server/express-server.js
+++ b/lib/tasks/server/express-server.js
@@ -144,7 +144,7 @@ module.exports = Task.extend({
 
     return this.startHttpServer()
       .then(function () {
-        var baseURL = cleanBaseURL(options.rootURL || options.baseURL);
+        var baseURL = options.rootURL === '' ? '/' : cleanBaseURL(options.rootURL || options.baseURL);
 
         options.ui.writeLine('Serving on http' + (options.ssl ? 's' : '') +
                              '://' + this.displayHost(options.host) +
diff --git a/lib/tasks/server/middleware/history-support/index.js b/lib/tasks/server/middleware/history-support/index.js
index ae40764fe..ed5713bac 100644
--- a/lib/tasks/server/middleware/history-support/index.js
+++ b/lib/tasks/server/middleware/history-support/index.js
@@ -40,7 +40,7 @@ HistorySupportAddon.prototype.addMiddleware = function(config) {
   var options = config.options;
   var watcher = options.watcher;
 
-  var baseURL = cleanBaseURL(options.rootURL || options.baseURL);
+  var baseURL = options.rootURL === '' ? '/' : cleanBaseURL(options.rootURL || options.baseURL);
   var baseURLRegexp = new RegExp('^' + baseURL);
 
   app.use(function(req, res, next) {
diff --git a/lib/tasks/server/middleware/serve-files/index.js b/lib/tasks/server/middleware/serve-files/index.js
index db0eb424c..c2342393b 100644
--- a/lib/tasks/server/middleware/serve-files/index.js
+++ b/lib/tasks/server/middleware/serve-files/index.js
@@ -25,7 +25,7 @@ ServeFilesAddon.prototype.serverMiddleware = function(options) {
     autoIndex: false // disable directory listings
   });
 
-  var baseURL = cleanBaseURL(options.rootURL || options.baseURL);
+  var baseURL = options.rootURL === '' ? '/' : cleanBaseURL(options.rootURL || options.baseURL);
 
   logger.info('serverMiddleware: baseURL: %s', baseURL);
 


Test patch:
diff --git a/lib/tasks/server/middleware/testem-url-rewriter/index.js b/lib/tasks/server/middleware/testem-url-rewriter/index.js
index 3760a88eb..f94d720a1 100644
--- a/lib/tasks/server/middleware/testem-url-rewriter/index.js
+++ b/lib/tasks/server/middleware/testem-url-rewriter/index.js
@@ -17,11 +17,11 @@ TestemUrlRewriterAddon.prototype.testemMiddleware = function(app) {
 
   this.project.ui.writeDeprecateLine(
     'Using the `baseURL` setting is deprecated, use `rootURL` instead.',
-    !(!config.rootURL && config.baseURL));
+    !(!('rootURL' in config) && config.baseURL));
 
   this.project.ui.writeWarnLine(
     'The `baseURL` and `rootURL` settings should not be used at the same time.',
-    !(config.rootURL && config.baseURL));
+    !(('rootURL' in config) && config.baseURL));
 
   var rootURL = cleanBaseURL(config.rootURL) || '/';
   logger.info('rootURL = %s', rootURL);
diff --git a/lib/tasks/server/middleware/tests-server/index.js b/lib/tasks/server/middleware/tests-server/index.js
index d28c16f96..86c6d9535 100644
--- a/lib/tasks/server/middleware/tests-server/index.js
+++ b/lib/tasks/server/middleware/tests-server/index.js
@@ -23,7 +23,7 @@ TestsServerAddon.prototype.serverMiddleware = function(config) {
   var options = config.options;
   var watcher = options.watcher;
 
-  var baseURL = cleanBaseURL(options.rootURL || options.baseURL);
+  var baseURL = options.rootURL === '' ? '/' : cleanBaseURL(options.rootURL || options.baseURL);
   var testsPath = baseURL + 'tests';
 
   app.use(function(req, res, next) {
diff --git a/tests/unit/tasks/server/express-server-test.js b/tests/unit/tasks/server/express-server-test.js
index f7fb9458d..1973725c9 100644
--- a/tests/unit/tasks/server/express-server-test.js
+++ b/tests/unit/tasks/server/express-server-test.js
@@ -145,6 +145,18 @@ describe('express-server', function() {
       });
     });
 
+    it('with empty rootURL', function() {
+      return subject.start({
+        host: undefined,
+        port: '1337',
+        rootURL: ''
+      }).then(function() {
+        var output = ui.output.trim().split(EOL);
+        expect(output[0]).to.equal('Serving on http://localhost:1337/');
+        expect(output.length).to.equal(1, 'expected only one line of output');
+      });
+    });
+
     it('address in use', function() {
       var preexistingServer = net.createServer();
       preexistingServer.listen(1337);