diff --git a/README.md b/README.md index 4e47ec7..ed571c8 100644 --- a/README.md +++ b/README.md @@ -160,3 +160,26 @@ Options are passed to `explorer(app, options)`. > Default: Read from package.json > Sets your API version. If not present, will read from your app's package.json. + +`auth`: **Object** + +> Optional config for setting api access token, can be used to rename the query parameter or set an auth header. + +> The object has 2 keys: +> - `in`: either `header` or `query` +> - `name`: the name of the query parameter or header +> +> The default sets the token as a query parameter with the name `access_token` + +> Example for setting the api key in a header named `x-api-key`: +> ``` +> { +> "loopback-component-explorer": { +> "mountPath": "/explorer", +> "auth": { +> "in": "header", +> "name": "x-api-key" +> } +> } +> } +> ``` diff --git a/index.js b/index.js index b588f7c..5f3d0d5 100644 --- a/index.js +++ b/index.js @@ -69,12 +69,17 @@ function routes(loopbackApplication, options) { // Get the path we're mounted at. It's best to get this from the referer // in case we're proxied at a deep path. var source = url.parse(req.headers.referer || '').pathname; + // strip index.html if present in referer + if (source && /\/index\.html$/.test(source)) { + source = source.replace(/\/index\.html$/, ''); + } // If no referer is available, use the incoming url. if (!source) { source = req.originalUrl.replace(/\/config.json(\?.*)?$/, ''); } res.send({ url: urlJoin(source, '/' + options.resourcePath), + auth: options.auth, }); }); diff --git a/public/lib/loadSwaggerUI.js b/public/lib/loadSwaggerUI.js index 595436c..369589b 100644 --- a/public/lib/loadSwaggerUI.js +++ b/public/lib/loadSwaggerUI.js @@ -27,6 +27,7 @@ $(function() { validatorUrl: null, url: config.url || '/swagger/resources', apiKey: '', + auth: config.auth, dom_id: 'swagger-ui-container', supportHeaderParams: true, onComplete: function(swaggerApi, swaggerUi) { @@ -76,12 +77,15 @@ $(function() { function setAccessToken(e) { e.stopPropagation(); // Don't let the default #explore handler fire e.preventDefault(); + var authOptions = window.swaggerUi.options.auth || {}; + var keyLocation = authOptions.in || 'query'; + var keyName = authOptions.name || 'access_token'; var key = $('#input_accessToken')[0].value; log('key: ' + key); if (key && key.trim() !== '') { log('added accessToken ' + key); var apiKeyAuth = - new SwaggerClient.ApiKeyAuthorization('access_token', key, 'query'); + new SwaggerClient.ApiKeyAuthorization(keyName, key, keyLocation); window.swaggerUi.api.clientAuthorizations.add('key', apiKeyAuth); accessToken = key; $('.accessTokenDisplay').text('Token Set.').addClass('set'); diff --git a/test/explorer.test.js b/test/explorer.test.js index 72ff1ee..e9ddf12 100644 --- a/test/explorer.test.js +++ b/test/explorer.test.js @@ -33,6 +33,40 @@ describe('explorer', function() { .get('/explorer/') .expect('Content-Type', /html/) .expect(200) + .end(function(err, res) { + if (err) return done(err); + + assert(!!~res.text.indexOf('LoopBack API Explorer'), + 'text does not contain expected string'); + + done(); + }); + }); + + it('should serve correct swagger-ui config', function(done) { + request(this.app) + .get('/explorer/config.json') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) return done(err); + + expect(res.body).to + .have.property('url', '/explorer/swagger.json'); + + done(); + }); + }); + }); + + describe('when filename is included in url', function() { + beforeEach(givenLoopBackAppWithExplorer()); + + it('should serve the explorer at /explorer/index.html', function(done) { + request(this.app) + .get('/explorer/index.html') + .expect('Content-Type', /html/) + .expect(200) .end(function(err, res) { if (err) throw err; @@ -46,6 +80,7 @@ describe('explorer', function() { it('should serve correct swagger-ui config', function(done) { request(this.app) .get('/explorer/config.json') + .set('Referer', 'http://example.com/explorer/index.html') .expect('Content-Type', /json/) .expect(200) .end(function(err, res) {