Skip to content

Commit

Permalink
feat(rest): add rest.router binding to allow customization
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed Oct 3, 2018
1 parent eb66820 commit e2c61d9
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 4 deletions.
6 changes: 4 additions & 2 deletions packages/rest/src/http-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import {RestBindings} from './keys';
import {RequestContext} from './request-context';

export class HttpHandler {
protected _routes: RoutingTable = new RoutingTable();
protected _apiDefinitions: SchemasObject;

public handleRequest: (request: Request, response: Response) => Promise<void>;

constructor(protected _rootContext: Context) {
constructor(
protected _rootContext: Context,
protected _routes = new RoutingTable(),
) {
this.handleRequest = (req, res) => this._handleRequest(req, res);
}

Expand Down
7 changes: 7 additions & 0 deletions packages/rest/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
import {HttpProtocol} from '@loopback/http-server';
import * as https from 'https';
import {ErrorWriterOptions} from 'strong-error-handler';
import {RestRouter} from './router';

/**
* RestServer-specific bindings
Expand Down Expand Up @@ -65,6 +66,12 @@ export namespace RestBindings {
* Internal binding key for http-handler
*/
export const HANDLER = BindingKey.create<HttpHandler>('rest.handler');

/**
* Internal binding key for rest router
*/
export const ROUTER = BindingKey.create<RestRouter>('rest.router');

/**
* Binding key for setting and injecting Reject action's error handling
* options.
Expand Down
10 changes: 9 additions & 1 deletion packages/rest/src/rest.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
createControllerFactoryForBinding,
Route,
RouteEntry,
RoutingTable,
} from './router/routing-table';

import {DefaultSequence, SequenceFunction, SequenceHandler} from './sequence';
Expand Down Expand Up @@ -281,7 +282,14 @@ export class RestServer extends Context implements Server, HttpServerLike {
// See https://github.com/strongloop/loopback-next/issues/433
if (this._httpHandler) return;

this._httpHandler = new HttpHandler(this);
const router = this.getSync(RestBindings.ROUTER, {optional: true});
let routingTable: RoutingTable;
if (router) {
routingTable = new RoutingTable(router);
} else {
routingTable = new RoutingTable();
}
this._httpHandler = new HttpHandler(this, routingTable);
for (const b of this.find('controllers.*')) {
const controllerName = b.key.replace(/^controllers\./, '');
const ctor = b.valueConstructor;
Expand Down
12 changes: 11 additions & 1 deletion packages/rest/test/acceptance/routing/routing.acceptance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {anOpenApiSpec, anOperationSpec} from '@loopback/openapi-spec-builder';
import {inject, Context, BindingScope} from '@loopback/context';

import {createUnexpectedHttpErrorLogger} from '../../helpers';
import {TrieRouter} from '../../../src';

/* # Feature: Routing
* - In order to build REST APIs
Expand Down Expand Up @@ -701,7 +702,16 @@ describe('Routing', () => {
.expect(200, 'hello');
});

it('sorts routes based on their specifics', async () => {
it('allows pluggable router', async () => {
const app = new RestApplication();
app.bind(RestBindings.ROUTER).toClass(TrieRouter);
const server = await app.getServer(RestServer);
const handler = await server.get(RestBindings.HANDLER);
// tslint:disable-next-line:no-any
expect((handler as any)._routes._router).to.be.instanceof(TrieRouter);
});

it('matches routes based on their specifics', async () => {
const app = new RestApplication();

app.route(
Expand Down

0 comments on commit e2c61d9

Please sign in to comment.