Merge branch 'release/1.5.0' into production
This commit is contained in:
commit
46dc9b1d4d
21
README.md
21
README.md
|
@ -25,7 +25,7 @@ app.listen(port);
|
||||||
|
|
||||||
## Advanced Usage
|
## Advanced Usage
|
||||||
|
|
||||||
Many aspects of the explorer are configurable.
|
Many aspects of the explorer are configurable.
|
||||||
|
|
||||||
See [options](#options) for a description of these options:
|
See [options](#options) for a description of these options:
|
||||||
|
|
||||||
|
@ -34,7 +34,10 @@ See [options](#options) for a description of these options:
|
||||||
app.use('/explorer', loopback.basicAuth('user', 'password'));
|
app.use('/explorer', loopback.basicAuth('user', 'password'));
|
||||||
app.use('/explorer', explorer(app, {
|
app.use('/explorer', explorer(app, {
|
||||||
basePath: '/custom-api-root',
|
basePath: '/custom-api-root',
|
||||||
swaggerDistRoot: '/swagger',
|
uiDirs: [
|
||||||
|
path.resolve(__dirname, 'public'),
|
||||||
|
path.resolve(__dirname, 'node_modules', 'swagger-ui')
|
||||||
|
]
|
||||||
apiInfo: {
|
apiInfo: {
|
||||||
'title': 'My API',
|
'title': 'My API',
|
||||||
'description': 'Explorer example app.'
|
'description': 'Explorer example app.'
|
||||||
|
@ -67,27 +70,27 @@ Options are passed to `explorer(app, options)`.
|
||||||
> and thus needs to report its endpoints as `https`, even though incoming traffic is auto-detected
|
> and thus needs to report its endpoints as `https`, even though incoming traffic is auto-detected
|
||||||
> as `http`.
|
> as `http`.
|
||||||
|
|
||||||
`swaggerDistRoot`: **String**
|
`uiDirs`: **Array of Strings**
|
||||||
|
|
||||||
> Sets a path within your application for overriding Swagger UI files.
|
> Sets a list of paths within your application for overriding Swagger UI files.
|
||||||
|
|
||||||
> If present, will search `swaggerDistRoot` first when attempting to load Swagger UI, allowing
|
> If present, will search `uiDirs` first when attempting to load Swagger UI,
|
||||||
> you to pick and choose overrides to the interface. Use this to style your explorer or
|
> allowing you to pick and choose overrides to the interface. Use this to
|
||||||
> add additional functionality.
|
> style your explorer or add additional functionality.
|
||||||
|
|
||||||
> See [index.html](public/index.html), where you may want to begin your overrides.
|
> See [index.html](public/index.html), where you may want to begin your overrides.
|
||||||
> The rest of the UI is provided by [Swagger UI](https://github.com/wordnik/swagger-ui).
|
> The rest of the UI is provided by [Swagger UI](https://github.com/wordnik/swagger-ui).
|
||||||
|
|
||||||
`apiInfo`: **Object**
|
`apiInfo`: **Object**
|
||||||
|
|
||||||
> Additional information about your API. See the
|
> Additional information about your API. See the
|
||||||
> [spec](https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#513-info-object).
|
> [spec](https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#513-info-object).
|
||||||
|
|
||||||
`resourcePath`: **String**
|
`resourcePath`: **String**
|
||||||
|
|
||||||
> Default: `'resources'`
|
> Default: `'resources'`
|
||||||
|
|
||||||
> Sets a different path for the
|
> Sets a different path for the
|
||||||
> [resource listing](https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing).
|
> [resource listing](https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing).
|
||||||
> You generally shouldn't have to change this.
|
> You generally shouldn't have to change this.
|
||||||
|
|
||||||
|
|
16
index.js
16
index.js
|
@ -47,15 +47,25 @@ function explorer(loopbackApplication, options) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Allow specifying a static file root for swagger files. Any files in
|
// Allow specifying a static file roots for swagger files. Any files in
|
||||||
// that folder will override those in the swagger-ui distribution.
|
// these folders will override those in the swagger-ui distribution.
|
||||||
// In this way one could e.g. make changes to index.html without having
|
// In this way one could e.g. make changes to index.html without having
|
||||||
// to worry about constantly pulling in JS updates.
|
// to worry about constantly pulling in JS updates.
|
||||||
|
if (options.uiDirs) {
|
||||||
|
options.uiDirs.forEach(function(dir) {
|
||||||
|
app.use(express.static(dir));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (options.swaggerDistRoot) {
|
if (options.swaggerDistRoot) {
|
||||||
|
console.warn('loopback-explorer: `swaggerDistRoot` is deprecated,' +
|
||||||
|
' use `uiDirs` instead');
|
||||||
app.use(express.static(options.swaggerDistRoot));
|
app.use(express.static(options.swaggerDistRoot));
|
||||||
}
|
}
|
||||||
|
|
||||||
// File in node_modules are overridden by a few customizations
|
// File in node_modules are overridden by a few customizations
|
||||||
app.use(express.static(STATIC_ROOT));
|
app.use(express.static(STATIC_ROOT));
|
||||||
|
|
||||||
// Swagger UI distribution
|
// Swagger UI distribution
|
||||||
app.use(express.static(SWAGGER_UI_ROOT));
|
app.use(express.static(SWAGGER_UI_ROOT));
|
||||||
|
|
||||||
|
|
|
@ -166,9 +166,9 @@ function addRoute(app, uri, doc, opts) {
|
||||||
if (hasBasePath) {
|
if (hasBasePath) {
|
||||||
var headers = req.headers;
|
var headers = req.headers;
|
||||||
// NOTE header names (keys) are always all-lowercase
|
// NOTE header names (keys) are always all-lowercase
|
||||||
|
var proto = headers['x-forwarded-proto'] || opts.protocol || req.protocol;
|
||||||
var host = headers['x-forwarded-host'] || headers.host;
|
var host = headers['x-forwarded-host'] || headers.host;
|
||||||
doc.basePath = (opts.protocol || req.protocol) + '://' +
|
doc.basePath = proto + '://' + host + initialPath;
|
||||||
host + initialPath;
|
|
||||||
}
|
}
|
||||||
res.status(200).send(doc);
|
res.status(200).send(doc);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "loopback-explorer",
|
"name": "loopback-explorer",
|
||||||
"version": "1.4.0",
|
"version": "1.5.0",
|
||||||
"description": "Browse and test your LoopBack app's APIs",
|
"description": "Browse and test your LoopBack app's APIs",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -2,6 +2,7 @@ var loopback = require('loopback');
|
||||||
var explorer = require('../');
|
var explorer = require('../');
|
||||||
var request = require('supertest');
|
var request = require('supertest');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var path = require('path');
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
|
|
||||||
describe('explorer', function() {
|
describe('explorer', function() {
|
||||||
|
@ -24,7 +25,7 @@ describe('explorer', function() {
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
assert(!!~res.text.indexOf('<title>StrongLoop API Explorer</title>'),
|
assert(!!~res.text.indexOf('<title>StrongLoop API Explorer</title>'),
|
||||||
'text does not contain expected string');
|
'text does not contain expected string');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -79,6 +80,32 @@ describe('explorer', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with custom front-end files', function() {
|
||||||
|
var app;
|
||||||
|
beforeEach(function setupExplorerWithUiDirs() {
|
||||||
|
app = loopback();
|
||||||
|
app.use('/explorer', explorer(app, {
|
||||||
|
uiDirs: [ path.resolve(__dirname, 'fixtures', 'dummy-swagger-ui') ]
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('overrides swagger-ui files', function(done) {
|
||||||
|
request(app).get('/explorer/swagger-ui.js')
|
||||||
|
.expect(200)
|
||||||
|
// expect the content of `dummy-swagger-ui/swagger-ui.js`
|
||||||
|
.expect('/* custom swagger-ui file */\n')
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('overrides strongloop overrides', function(done) {
|
||||||
|
request(app).get('/explorer/')
|
||||||
|
.expect(200)
|
||||||
|
// expect the content of `dummy-swagger-ui/index.html`
|
||||||
|
.expect('custom index.html\n')
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function givenLoopBackAppWithExplorer(explorerBase) {
|
function givenLoopBackAppWithExplorer(explorerBase) {
|
||||||
return function(done) {
|
return function(done) {
|
||||||
var app = this.app = loopback();
|
var app = this.app = loopback();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
custom index.html
|
|
@ -0,0 +1 @@
|
||||||
|
/* custom swagger-ui file */
|
|
@ -93,6 +93,18 @@ describe('swagger definition', function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('respects X-Forwarded-Proto header (behind a proxy)', function(done) {
|
||||||
|
var app = givenAppWithSwagger();
|
||||||
|
getAPIDeclaration(app, 'products')
|
||||||
|
.set('X-Forwarded-Proto', 'https')
|
||||||
|
.end(function(err, res) {
|
||||||
|
if (err) return done(err);
|
||||||
|
var baseUrl = url.parse(res.body.basePath);
|
||||||
|
expect(baseUrl.protocol).to.equal('https:');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Model definition attributes', function() {
|
describe('Model definition attributes', function() {
|
||||||
|
|
Loading…
Reference in New Issue