diff --git a/lib/swagger.js b/lib/swagger.js index 3572c81..b25d517 100644 --- a/lib/swagger.js +++ b/lib/swagger.js @@ -156,6 +156,11 @@ function addRoute(app, uri, doc, opts) { var hasBasePath = Object.keys(doc).indexOf('basePath') !== -1; var initialPath = doc.basePath || ''; + // Remove the trailing slash, see + // https://github.com/strongloop/loopback-explorer/issues/48 + if (initialPath[initialPath.length-1] === '/') + initialPath = initialPath.slice(0, -1); + app.get(urlJoin('/', uri), function(req, res) { // There's a few forces at play that require this "hack". The Swagger spec diff --git a/test/explorer.test.js b/test/explorer.test.js index 2a17a15..c3b4aeb 100644 --- a/test/explorer.test.js +++ b/test/explorer.test.js @@ -4,6 +4,7 @@ var request = require('supertest'); var assert = require('assert'); var path = require('path'); var expect = require('chai').expect; +var urlJoin = require('../lib/url-join'); describe('explorer', function() { @@ -78,6 +79,26 @@ describe('explorer', function() { done(); }); }); + + it('removes trailing slash from baseUrl', function(done) { + // SwaggerUI builds resource URL by concatenating basePath + resourcePath + // Since the resource paths are always startign with a slash, + // if the basePath ends with a slash too, an incorrect URL is produced + var app = loopback(); + app.set('restApiRoot', '/'); + configureRestApiAndExplorer(app); + + request(app) + .get('/explorer/resources/products') + .expect(200) + .end(function(err, res) { + if (err) return done(err); + var baseUrl = res.body.basePath; + var apiPath = res.body.apis[0].path; + expect(baseUrl + apiPath).to.match(/http:\/\/[^\/]+\/products/); + done(); + }); + }); }); describe('with custom front-end files', function() { @@ -146,7 +167,7 @@ describe('explorer', function() { } function configureRestApiAndExplorer(app, explorerBase) { - var Product = loopback.Model.extend('product'); + var Product = loopback.PersistedModel.extend('product'); Product.attachTo(loopback.memory()); app.model(Product);