I'm creating a layer of abstraction around Express JS and I've encountered a problem. Considering the following code (see bottom), when calling registerRoute and hitting the line:
expressFnc(route, (req: any, res: any, next: any) => dummy(req, res, next));
I am encountering the error:
Cannot read property 'lazyrouter' of undefined
In this context 'this', I assume, applies to ExpressJS (lib/application.js:479:10).
const express = require("express");
export class ExpressHttpHost implements IHttpHost {
private host: any = express();
private contentResolver?: ContentResolver;
public configure(contentResolver: ContentResolver): void {
this.contentResolver = contentResolver;
}
public registerRoute(
route: string,
verb: HttpVerb,
handler: (request: HttpRequest) => HttpResponse,
): void {
switch (verb) {
case HttpVerb.Get:
this.createDummyRequest(this.host.get, route, handler);
break;
case HttpVerb.Delete:
this.createDummyRequest(this.host.delete, route, handler);
break;
case HttpVerb.Options:
this.createDummyRequest(this.host.options, route, handler);
break;
case HttpVerb.Patch:
this.createDummyRequest(this.host.patch, route, handler);
break;
case HttpVerb.Post:
this.createDummyRequest(this.host.post, route, handler);
break;
case HttpVerb.Put:
this.createDummyRequest(this.host.put, route, handler);
break;
case HttpVerb.All:
this.createDummyRequest(this.host.get, route, handler);
this.createDummyRequest(this.host.delete, route, handler);
this.createDummyRequest(this.host.options, route, handler);
this.createDummyRequest(this.host.patch, route, handler);
this.createDummyRequest(this.host.post, route, handler);
this.createDummyRequest(this.host.put, route, handler);
break;
default:
throw new Error("Verb is not supported.");
}
}
public start(options: IHttpHostOptions): void {
this.host.listen(options.port ? options.port : 80);
}
private createHttpRequest(expressReq: any): HttpRequest {
return new HttpRequest(
expressReq.headers,
expressReq.params,
expressReq.body,
);
}
private createDummyRequest(expressFnc: any, route: string, handler: (request: HttpRequest) => HttpResponse): void {
const dummy = (expressReq: any, expressRes: any, next: any) => {
const httpRequest = this.createHttpRequest(expressReq);
const response = handler(httpRequest);
const responseStatus = response.status();
const responseMimeType = response.mimeType();
const responseContent = response.content(this.contentResolver);
expressRes.set("Content-Type", responseMimeType);
expressRes.status(responseStatus);
expressRes.send(responseContent);
next();
};
expressFnc(route, (req: any, res: any, next: any) => dummy(req, res, next));
}
}
This might happen because express functions when passed as arguments loose reference to the host object. Try manually binding them back. See the bindings below in the switch:
const express = require("express");
export class ExpressHttpHost implements IHttpHost {
private host: any = express();
private contentResolver?: ContentResolver;
public configure(contentResolver: ContentResolver): void {
this.contentResolver = contentResolver;
}
public registerRoute(
route: string,
verb: HttpVerb,
handler: (request: HttpRequest) => HttpResponse,
): void {
switch (verb) {
case HttpVerb.Get:
this.createDummyRequest(this.host.get.bind(this.host), route, handler);
break;
case HttpVerb.Delete:
this.createDummyRequest(this.host.delete.bind(this.host), route, handler);
break;
case HttpVerb.Options:
this.createDummyRequest(this.host.options.bind(this.host), route, handler);
break;
case HttpVerb.Patch:
this.createDummyRequest(this.host.patch.bind(this.host), route, handler);
break;
case HttpVerb.Post:
this.createDummyRequest(this.host.post.bind(this.host), route, handler);
break;
case HttpVerb.Put:
this.createDummyRequest(this.host.put.bind(this.host), route, handler);
break;
case HttpVerb.All:
this.createDummyRequest(this.host.get.bind(this.host), route, handler);
this.createDummyRequest(this.host.delete.bind(this.host), route, handler);
this.createDummyRequest(this.host.options.bind(this.host), route, handler);
this.createDummyRequest(this.host.patch.bind(this.host), route, handler);
this.createDummyRequest(this.host.post.bind(this.host), route, handler);
this.createDummyRequest(this.host.put.bind(this.host), route, handler);
break;
default:
throw new Error("Verb is not supported.");
}
}
public start(options: IHttpHostOptions): void {
this.host.listen(options.port ? options.port : 80);
}
private createHttpRequest(expressReq: any): HttpRequest {
return new HttpRequest(
expressReq.headers,
expressReq.params,
expressReq.body,
);
}
private createDummyRequest(expressFnc: any, route: string, handler: (request: HttpRequest) => HttpResponse): void {
const dummy = (expressReq: any, expressRes: any, next: any) => {
const httpRequest = this.createHttpRequest(expressReq);
const response = handler(httpRequest);
const responseStatus = response.status();
const responseMimeType = response.mimeType();
const responseContent = response.content(this.contentResolver);
expressRes.set("Content-Type", responseMimeType);
expressRes.status(responseStatus);
expressRes.send(responseContent);
next();
};
expressFnc(route, (req: any, res: any, next: any) => dummy(req, res, next));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With