Skip to content

Commit

Permalink
feat(rest): push route(verb, path, spec, fn) down to RestServer
Browse files Browse the repository at this point in the history
Move the implementation of 4-arg version of "route` method from
RestApplication to RestServer, simplify RestApplication's "route"
to delegate the implementation to RestServer.
  • Loading branch information
bajtos authored and raymondfeng committed Oct 22, 2018
1 parent b6ff7b7 commit c49b65a
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 31 deletions.
45 changes: 35 additions & 10 deletions packages/rest/src/rest.application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Application, ApplicationConfig, Server} from '@loopback/core';
import {RestComponent} from './rest.component';
import {SequenceHandler, SequenceFunction} from './sequence';
import {Binding, Constructor} from '@loopback/context';
import {Application, ApplicationConfig, Server} from '@loopback/core';
import {OpenApiSpec, OperationObject} from '@loopback/openapi-v3-types';
import {PathParams} from 'express-serve-static-core';
import {ServeStaticOptions} from 'serve-static';
import {format} from 'util';
import {RestBindings} from './keys';
import {RestServer, HttpRequestListener, HttpServerLike} from './rest.server';
import {RestComponent} from './rest.component';
import {HttpRequestListener, HttpServerLike, RestServer} from './rest.server';
import {
RouteEntry,
ControllerClass,
ControllerFactory,
Route,
RouteEntry,
} from './router/routing-table';
import {OperationObject, OpenApiSpec} from '@loopback/openapi-v3-types';
import {ServeStaticOptions} from 'serve-static';
import {PathParams} from 'express-serve-static-core';
import {SequenceFunction, SequenceHandler} from './sequence';

export const ERR_NO_MULTI_SERVER = format(
'RestApplication does not support multiple servers!',
Expand Down Expand Up @@ -127,6 +126,29 @@ export class RestApplication extends Application implements HttpServerLike {
methodName: string,
): Binding;

/**
* Register a new route invoking a handler function.
*
* ```ts
* function greet(name: string) {
* return `hello ${name}`;
* }
* app.route('get', '/', operationSpec, greet);
* ```
*
* @param verb HTTP verb of the endpoint
* @param path URL path of the endpoint
* @param spec The OpenAPI spec describing the endpoint (operation)
* @param handler The function to invoke with the request parameters
* described in the spec.
*/
route(
verb: string,
path: string,
spec: OperationObject,
handler: Function,
): Binding;

/**
* Register a new route.
*
Expand Down Expand Up @@ -172,7 +194,10 @@ export class RestApplication extends Application implements HttpServerLike {
return server.route(routeOrVerb);
} else if (arguments.length === 4) {
return server.route(
new Route(routeOrVerb, path!, spec!, controllerCtorOrHandler!),
routeOrVerb,
path!,
spec!,
controllerCtorOrHandler as Function,
);
} else {
return server.route(
Expand Down
46 changes: 40 additions & 6 deletions packages/rest/src/rest.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,30 @@ export class RestServer extends Context implements Server, HttpServerLike {
): Binding;

/**
* Register a new route.
* Register a new route invoking a handler function.
*
* ```ts
* function greet(name: string) {
* return `hello ${name}`;
* }
* app.route('get', '/', operationSpec, greet);
* ```
*
* @param verb HTTP verb of the endpoint
* @param path URL path of the endpoint
* @param spec The OpenAPI spec describing the endpoint (operation)
* @param handler The function to invoke with the request parameters
* described in the spec.
*/
route(
verb: string,
path: string,
spec: OperationObject,
handler: Function,
): Binding;

/**
* Register a new generic route.
*
* ```ts
* function greet(name: string) {
Expand All @@ -534,12 +557,12 @@ export class RestServer extends Context implements Server, HttpServerLike {
*/
route(route: RouteEntry): Binding;

route<I>(
route<T>(
routeOrVerb: RouteEntry | string,
path?: string,
spec?: OperationObject,
controllerCtor?: ControllerClass<I>,
controllerFactory?: ControllerFactory<I>,
controllerCtorOrHandler?: ControllerClass<T> | Function,
controllerFactory?: ControllerFactory<T>,
methodName?: string,
): Binding {
if (typeof routeOrVerb === 'object') {
Expand All @@ -563,7 +586,18 @@ export class RestServer extends Context implements Server, HttpServerLike {
});
}

if (!controllerCtor) {
if (arguments.length === 4) {
if (!controllerCtorOrHandler) {
throw new AssertionError({
message: 'handler function is required for a handler-based route',
});
}
return this.route(
new Route(routeOrVerb, path, spec, controllerCtorOrHandler as Function),
);
}

if (!controllerCtorOrHandler) {
throw new AssertionError({
message: 'controller is required for a controller-based route',
});
Expand All @@ -580,7 +614,7 @@ export class RestServer extends Context implements Server, HttpServerLike {
routeOrVerb,
path,
spec,
controllerCtor,
controllerCtorOrHandler as ControllerClass<T>,
controllerFactory,
methodName,
),
Expand Down
7 changes: 2 additions & 5 deletions packages/rest/test/acceptance/routing/routing.acceptance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import {
Request,
Response,
Route,
RestBindings,
RestServer,
RestComponent,
Expand Down Expand Up @@ -408,8 +407,7 @@ describe('Routing', () => {
return `hello ${name}`;
}

const route = new Route('get', '/greet', routeSpec, greet);
server.route(route);
server.route('get', '/greet', routeSpec, greet);

const client = whenIMakeRequestTo(server);
await client.get('/greet?name=world').expect(200, 'hello world');
Expand Down Expand Up @@ -609,8 +607,7 @@ describe('Routing', () => {
return `hello ${name}`;
}

const route = new Route('get', '/greet', routeSpec, greet);
app.route(route);
app.route('get', '/greet', routeSpec, greet);

await whenIMakeRequestTo(app)
.get('/greet?name=world')
Expand Down
8 changes: 4 additions & 4 deletions packages/rest/test/integration/rest.server.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
httpsGetAsync,
givenHttpServerConfig,
} from '@loopback/testlab';
import {Route, RestBindings, RestServer, RestComponent} from '../..';
import {RestBindings, RestServer, RestComponent} from '../..';
import {IncomingMessage, ServerResponse} from 'http';
import * as yaml from 'js-yaml';
import * as path from 'path';
Expand Down Expand Up @@ -238,7 +238,7 @@ describe('RestServer (integration)', () => {
},
},
};
server.route(new Route('get', '/greet', greetSpec, function greet() {}));
server.route('get', '/greet', greetSpec, function greet() {});

const response = await createClientForHandler(server.requestHandler).get(
'/openapi.json',
Expand Down Expand Up @@ -330,7 +330,7 @@ describe('RestServer (integration)', () => {
},
},
};
server.route(new Route('get', '/greet', greetSpec, function greet() {}));
server.route('get', '/greet', greetSpec, function greet() {});

const response = await createClientForHandler(server.requestHandler).get(
'/openapi.yaml',
Expand Down Expand Up @@ -372,7 +372,7 @@ paths:
},
},
};
server.route(new Route('get', '/greet', greetSpec, function greet() {}));
server.route('get', '/greet', greetSpec, function greet() {});

const response = await createClientForHandler(server.requestHandler).get(
'/explorer',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {expect, validateApiSpec} from '@loopback/testlab';
import {Application} from '@loopback/core';
import {
RestServer,
Route,
RestComponent,
createControllerFactoryForClass,
} from '../../..';
Expand Down Expand Up @@ -51,9 +50,7 @@ describe('RestServer.getApiSpec()', () => {

it('binds a route via app.route(route)', () => {
function greet() {}
const binding = server.route(
new Route('get', '/greet', {responses: {}}, greet),
);
const binding = server.route('get', '/greet', {responses: {}}, greet);
expect(binding.key).to.eql('routes.get %2Fgreet');
expect(binding.tagNames).containEql('route');
});
Expand All @@ -77,7 +74,7 @@ describe('RestServer.getApiSpec()', () => {

it('returns routes registered via app.route(route)', () => {
function greet() {}
server.route(new Route('get', '/greet', {responses: {}}, greet));
server.route('get', '/greet', {responses: {}}, greet);

const spec = server.getApiSpec();
expect(spec.paths).to.eql({
Expand Down Expand Up @@ -195,7 +192,7 @@ describe('RestServer.getApiSpec()', () => {
);

function greet() {}
server.route(new Route('get', '/greet', {responses: {}}, greet));
server.route('get', '/greet', {responses: {}}, greet);

const spec = server.getApiSpec();
expect(spec.paths).to.eql({
Expand Down

0 comments on commit c49b65a

Please sign in to comment.