diff --git a/README.md b/README.md index f962d0f..882e104 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,16 @@ Options are passed to `explorer(app, options)`. > to a path different than '/api', e.g. with > `loopback.use('/custom-api-root', loopback.rest()); +`protocol`: **String** + +> Default: `null` + +> A hard override for the outgoing protocol (`http` or `https`) that is designated in Swagger +> resource documents. By default, `loopback-explorer` will write the protocol that was used to retrieve +> the doc. This option is useful if, for instance, your API sits behind an SSL terminator +> and thus needs to report its endpoints as `https`, even though incoming traffic is auto-detected +> as `http`. + `swaggerDistRoot`: **String** > Sets a path within your application for overriding Swagger UI files. diff --git a/lib/swagger.js b/lib/swagger.js index 2bea1a1..5d76098 100644 --- a/lib/swagger.js +++ b/lib/swagger.js @@ -24,7 +24,7 @@ var routeHelper = require('./route-helper'); * @param {Object} opts Options. */ function Swagger(loopbackApplication, swaggerApp, opts) { - opts = _defaults({}, opts, { + _defaults(opts || {}, { swaggerVersion: '1.2', basePath: loopbackApplication.get('restApiRoot') || '/api', resourcePath: 'resources', @@ -48,7 +48,7 @@ function Swagger(loopbackApplication, swaggerApp, opts) { // Add the getter for this doc. var docPath = urlJoin(opts.resourcePath, aClass.http.path); - addRoute(swaggerApp, docPath, doc); + addRoute(swaggerApp, docPath, doc, opts); }); // A route is an endpoint, such as /users/findOne. @@ -73,7 +73,7 @@ function Swagger(loopbackApplication, swaggerApp, opts) { * resources available on the system, and where to find more * information about them. */ - addRoute(swaggerApp, opts.resourcePath, resourceDoc); + addRoute(swaggerApp, opts.resourcePath, resourceDoc, opts); } /** @@ -82,7 +82,7 @@ function Swagger(loopbackApplication, swaggerApp, opts) { * @param {String} uri Path from which to serve the doc. * @param {Object} doc Doc to serve. */ -function addRoute(app, uri, doc) { +function addRoute(app, uri, doc, opts) { var hasBasePath = Object.keys(doc).indexOf('basePath') !== -1; var initialPath = doc.basePath || ''; @@ -100,7 +100,8 @@ function addRoute(app, uri, doc) { if (hasBasePath) { var headers = req.headers; var host = headers.Host || headers.host; - doc.basePath = req.protocol + '://' + host + initialPath; + doc.basePath = (opts.protocol || req.protocol) + '://' + + host + initialPath; } res.status(200).send(doc); }); diff --git a/test/swagger.test.js b/test/swagger.test.js index 2fd6bd2..1cd0a5b 100644 --- a/test/swagger.test.js +++ b/test/swagger.test.js @@ -69,6 +69,18 @@ describe('swagger definition', function() { done(); }); }); + + it('respects a hardcoded protocol (behind SSL terminator)', function(done){ + var app = mountSwagger({protocol: 'https'}); + + var getReq = getAPIDeclaration(app, 'products'); + getReq.end(function(err, res) { + if (err) return done(err); + var parsed = url.parse(res.body.basePath); + expect(parsed.protocol).to.equal('https:'); + done(); + }); + }); }); describe('Model definition attributes', function() {