Skip to content

Commit

Permalink
fix: fix static assets router blocking controller registration
Browse files Browse the repository at this point in the history
Fix static assets router blocking registration of controllers
  • Loading branch information
Hage Yaapa committed Nov 5, 2018
1 parent 1bcdb5b commit 936abe2
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 2 deletions.
8 changes: 8 additions & 0 deletions packages/rest/fixtures/dir-a/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<header>
<title>Test Dir</title>
</header>
<body>
<h1>Hello, Dir!</h1>
</body>
</html>
26 changes: 25 additions & 1 deletion packages/rest/src/rest.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ export class RestServer extends Context implements Server, HttpServerLike {
this._setupOperation(verb, path, routeSpec);
}
}

this.staticRoutes.forEach(route => {
const {path, rootDir, options} = route;
this.httpHandler.registerStaticAssets(path, rootDir, options);
});
}

private _setupOperation(verb: string, path: string, spec: OperationObject) {
Expand Down Expand Up @@ -605,6 +610,8 @@ export class RestServer extends Context implements Server, HttpServerLike {
);
}

private staticRoutes: staticAssetOptions[] = [];

/**
* Mount static assets to the REST server.
* See https://expressjs.com/en/4x/api.html#express.static
Expand All @@ -614,7 +621,15 @@ export class RestServer extends Context implements Server, HttpServerLike {
* @param options Options for serve-static
*/
static(path: PathParams, rootDir: string, options?: ServeStaticOptions) {
this.httpHandler.registerStaticAssets(path, rootDir, options);
if (this._httpHandler) {
this.httpHandler.registerStaticAssets(path, rootDir, options);
} else {
this.staticRoutes.push({
path,
rootDir,
options,
});
}
}

/**
Expand Down Expand Up @@ -844,3 +859,12 @@ export interface RestServerOptions {
* @interface RestServerConfig
*/
export type RestServerConfig = RestServerOptions & HttpServerOptions;

/**
* Options for handling static assets
*/
export type staticAssetOptions = {
path: PathParams;
rootDir: string;
options?: ServeStaticOptions;
};
60 changes: 59 additions & 1 deletion packages/rest/test/integration/rest.application.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {createRestAppClient, Client, expect} from '@loopback/testlab';
import {RestApplication} from '../..';
import * as path from 'path';
import * as fs from 'fs';
import {RestServer, RestServerConfig} from '../../src';
import {RestServer, RestServerConfig, get} from '../../src';

const FIXTURES = path.resolve(__dirname, '../../../fixtures');

Expand Down Expand Up @@ -49,6 +49,41 @@ describe('RestApplication (integration)', () => {
.expect(content);
});

it('allows static assets to be mounted on multiple paths', async () => {
givenApplication();
restApp.static('/html-0', FIXTURES);
restApp.static('/html-1', FIXTURES);
await restApp.start();
const content = fs
.readFileSync(path.join(FIXTURES, 'index.html'))
.toString('utf-8');
client = createRestAppClient(restApp);
await client
.get('/html-0/index.html')
.expect(200)
.expect(content);
await client
.get('/html-1/index.html')
.expect(200)
.expect(content);
});

it('allows static assets to be mounted on the same path multiple times', async () => {
const dirA = path.join(FIXTURES, 'dir-a');
givenApplication();
restApp.static('/html', dirA);
restApp.static('/html', FIXTURES);
await restApp.start();
const content = fs
.readFileSync(path.join(dirA, 'index.html'))
.toString('utf-8');
client = createRestAppClient(restApp);
await client
.get('/html/index.html')
.expect(200)
.expect(content);
});

it('returns 404 if asset is not found', async () => {
givenApplication();
restApp.static('/', FIXTURES);
Expand Down Expand Up @@ -92,6 +127,19 @@ describe('RestApplication (integration)', () => {
.expect('Hello');
});

it('gives precedence to API controllers over static assets', async () => {
const root = FIXTURES;
givenApplication();
restApp.static('/html', root);
restApp.controller(DummyController);
await restApp.start();
client = createRestAppClient(restApp);
await client
.get('/html')
.expect(200)
.expect('Hello');
});

it('returns RestServer instance', async () => {
givenApplication();
const restServer = restApp.restServer;
Expand Down Expand Up @@ -128,4 +176,14 @@ describe('RestApplication (integration)', () => {
options = options || {rest: {port: 0, host: '127.0.0.1'}};
restApp = new RestApplication(options);
}

class DummyController {
constructor() {}
@get('/html', {
responses: {},
})
ping(): string {
return 'Hello';
}
}
});
43 changes: 43 additions & 0 deletions packages/rest/test/integration/rest.server.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,49 @@ describe('RestServer (integration)', () => {
.expect(200, content);
});

it('allows static assets to be mounted on multiple paths', async () => {
const root = FIXTURES;
const server = await givenAServer({
rest: {
port: 0,
},
});

server.static('/html-0', root);
server.static('/html-1', root);
const content = fs
.readFileSync(path.join(root, 'index.html'))
.toString('utf-8');
await createClientForHandler(server.requestHandler)
.get('/html-0/index.html')
.expect('Content-Type', /text\/html/)
.expect(200, content);
await createClientForHandler(server.requestHandler)
.get('/html-1/index.html')
.expect('Content-Type', /text\/html/)
.expect(200, content);
});

it('allows static assets to be mounted on the same path multiple times', async () => {
const root = FIXTURES;
const dirA = path.join(root, 'dir-a');
const server = await givenAServer({
rest: {
port: 0,
},
});

server.static('/html', dirA);
server.static('/html', root);
const content = fs
.readFileSync(path.join(dirA, 'index.html'))
.toString('utf-8');
await createClientForHandler(server.requestHandler)
.get('/html/index.html')
.expect('Content-Type', /text\/html/)
.expect(200, content);
});

it('allows static assets via api after start', async () => {
const root = FIXTURES;
const server = await givenAServer({
Expand Down

0 comments on commit 936abe2

Please sign in to comment.