Skip to content

Commit

Permalink
Custom router wan't used (#31)
Browse files Browse the repository at this point in the history
* Introduce behavior when custom router isn't used

* Use custom router passed from arguments

* Provide a way to setup routing configuration
  • Loading branch information
maxmalov authored and remojansen committed Feb 6, 2017
1 parent fe7a0db commit 74d46f3
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 6 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ let router = express.Router({
let server = new InversifyExpressServer(container, router);
```

By default server will serve the API at `/` path, but sometimes you might need to use different root namespace, for
example all routes should start with `/api/v1`. It is possible to pass this setting via routing configuration to
`InversifyExpressServer`

```ts
let container = new Container();

let server = new InversifyExpressServer(container, null, { rootPath: "/api/v1" });
```

## Decorators

### `@Controller(path, [middleware, ...])`
Expand Down
4 changes: 3 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ const METADATA_KEY = {
controllerMethod: "_controller-method"
};

export { TYPE, METADATA_KEY };
const DEFAULT_ROUTING_ROOT_PATH = "/";

export { TYPE, METADATA_KEY, DEFAULT_ROUTING_ROOT_PATH };
4 changes: 4 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ namespace interfaces {
(app: express.Application): void;
}

export interface RoutingConfig {
rootPath: string;
}

}

export { interfaces };
20 changes: 15 additions & 5 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as express from "express";
import * as inversify from "inversify";
import { interfaces } from "./interfaces";
import { TYPE, METADATA_KEY } from "./constants";
import { TYPE, METADATA_KEY, DEFAULT_ROUTING_ROOT_PATH } from "./constants";

/**
* Wrapper for the express server.
Expand All @@ -13,6 +13,7 @@ export class InversifyExpressServer {
private _app: express.Application = express();
private _configFn: interfaces.ConfigFunction;
private _errorConfigFn: interfaces.ConfigFunction;
private _routingConfig: interfaces.RoutingConfig;

/**
* Wrapper for the express server.
Expand All @@ -21,10 +22,14 @@ export class InversifyExpressServer {
*/
constructor(
container: inversify.interfaces.Container,
customRouter?: express.Router
customRouter?: express.Router,
routingConfig?: interfaces.RoutingConfig
) {
this._container = container;
this._router = customRouter || express.Router();
this._routingConfig = routingConfig || {
rootPath: DEFAULT_ROUTING_ROOT_PATH
};
}

/**
Expand Down Expand Up @@ -93,12 +98,17 @@ export class InversifyExpressServer {

methodMetadata.forEach((metadata: interfaces.ControllerMethodMetadata) => {
let handler: express.RequestHandler = this.handlerFactory(controllerMetadata.target.name, metadata.key);
router[metadata.method](metadata.path, ...metadata.middleware, handler);
this._router[metadata.method](
`${controllerMetadata.path}${metadata.path}`,
...controllerMetadata.middleware,
...metadata.middleware,
handler
);
});

this._app.use(controllerMetadata.path, ...controllerMetadata.middleware, router);
}
});

this._app.use(this._routingConfig.rootPath, this._router);
}

private handlerFactory(controllerName: any, key: string): express.RequestHandler {
Expand Down
54 changes: 54 additions & 0 deletions test/framework.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,60 @@ describe("Integration Tests:", () => {
.get("/")
.expect(200, JSON.stringify(result), done);
});

it("should use custom router passed from configuration", () => {
@injectable()
@Controller("/CaseSensitive")
class TestController {
@Get("/Endpoint") public get() {
return "Such Text";
}
}
container.bind<interfaces.Controller>(TYPE.Controller).to(TestController).whenTargetNamed("TestController");

const customRouter = express.Router({
caseSensitive: true
});

server = new InversifyExpressServer(container, customRouter);
const app = server.build();

const expectedSuccess = request(app)
.get("/CaseSensitive/Endpoint")
.expect(200, "Such Text");

const expectedNotFound1 = request(app)
.get("/casesensitive/endpoint")
.expect(404);

const expectedNotFound2 = request(app)
.get("/CaseSensitive/endpoint")
.expect(404);

return Promise.all([
expectedSuccess,
expectedNotFound1,
expectedNotFound2
]);

});

it("should use custom routing configuration", () => {
@injectable()
@Controller("/ping")
class TestController {
@Get("/endpoint") public get() {
return "pong";
}
}
container.bind<interfaces.Controller>(TYPE.Controller).to(TestController).whenTargetNamed("TestController");

server = new InversifyExpressServer(container, null, { rootPath: "/api/v1" });

return request(server.build())
.get("/api/v1/ping/endpoint")
.expect(200, "pong");
});
});


Expand Down
18 changes: 18 additions & 0 deletions test/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,22 @@ describe("Unit Test: InversifyExpressServer", () => {

});

it("Should allow to provide custom routing configuration", () => {

let container = new Container();

let routingConfig = {
rootPath: "/such/root/path"
};

let serverWithDefaultConfig = new InversifyExpressServer(container);
let serverWithCustomConfig = new InversifyExpressServer(container, null, routingConfig);

expect((serverWithCustomConfig as any)._routingConfig).to.eq(routingConfig);
expect((serverWithDefaultConfig as any)._routingConfig).to.not.eql(
(serverWithCustomConfig as any)._routingConfig
);

});

});

0 comments on commit 74d46f3

Please sign in to comment.