Skip to content

Commit

Permalink
Merge pull request #45 from ujjwalguptaofficial/optimize-head-options…
Browse files Browse the repository at this point in the history
…-method

Optimize head options method
  • Loading branch information
ujjwalguptaofficial authored Nov 15, 2024
2 parents 65a08fe + 4db12a9 commit c53ba5a
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 44 deletions.
14 changes: 12 additions & 2 deletions src/decorators/req_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ function put(...args) {
return wrapMethodDecorator(args, createWorkerForPut);
}

function option(target, key: string): void;
function option(route: string): MethodDecorator;
function option(...args) {
return wrapMethodDecorator(args, createWorkerForOption);
}

function registerWorkerAndCreate(target, methodName, httpMethod: HTTP_METHOD, routes: string[]) {
const routeArg = (routes.length === 0 ? null : routes[0]);
(worker as any)(httpMethod)(
Expand Down Expand Up @@ -66,7 +72,11 @@ function createWorkerForDelete(target: any, methodName: string, ...routes: strin
registerWorkerAndCreate(target, methodName, HTTP_METHOD.Delete, routes);
}

function createWorkerForOption(target: any, methodName: string, ...routes: string[]) {
registerWorkerAndCreate(target, methodName, HTTP_METHOD.Options, routes);
}

export const http = {
get, post, delete: del,
patch, put
}
patch, put, option
}
12 changes: 8 additions & 4 deletions src/decorators/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ export function worker(...args) {
return wrapMethodDecorator(args, createWorker);
}

const allHttpMethod = [
const allHttpMethod = Object.seal([
HTTP_METHOD.Delete,
HTTP_METHOD.Get,
HTTP_METHOD.Post,
HTTP_METHOD.Patch,
HTTP_METHOD.Put
];
HTTP_METHOD.Put,
HTTP_METHOD.Head,
]);

function createWorker(target: any, methodName: string, ...allowedMethods: HTTP_METHOD[]) {
const className = (target.constructor.name as string);
if (allowedMethods.includes(HTTP_METHOD.Get)) {
allowedMethods.push(HTTP_METHOD.Head);
}
const actionInfo: IWorkerInfo = {
workerName: methodName,
methodsAllowed: allowedMethods.length === 0 ? allHttpMethod : allowedMethods,
Expand All @@ -27,4 +31,4 @@ function createWorker(target: any, methodName: string, ...allowedMethods: HTTP_M
values: []
};
RouteHandler.addWorker(actionInfo, className);
}
}
11 changes: 6 additions & 5 deletions src/handlers/request_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,13 @@ export class RequestHandler extends RequestHandlerHelper {
private async onRouteMatched_() {
const routeMatchInfo = this.routeMatchInfo_;
const workerInfo = routeMatchInfo.workerInfo;

if (workerInfo == null) {
return () => {
return this.request.method === HTTP_METHOD.Options ?
this.onRequestOptions(routeMatchInfo.allowedHttpMethod) :
this.onMethodNotAllowed(routeMatchInfo.allowedHttpMethod);
switch (this.request.method) {
case HTTP_METHOD.Options:
return this.onRequestOptions(routeMatchInfo.allowedHttpMethod);
}
return this.onMethodNotAllowed(routeMatchInfo.allowedHttpMethod);
}
}

Expand Down Expand Up @@ -215,4 +216,4 @@ export class RequestHandler extends RequestHandlerHelper {
return this.handleFinalResult_;
// }
}
}
}
17 changes: 10 additions & 7 deletions src/handlers/request_handler_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ export class RequestHandlerHelper {

protected onRequestOptions(allowedMethods: HTTP_METHOD[]) {
this.response.setHeader("Allow", allowedMethods.join(","));
return this.onResultFromError_(textResult(""));
this.controllerResult = textResult("");
return this.endResponse_(
MIME_TYPE.Text,
false
);
}

private onResultFromError_(result: IHttpResult) {
Expand Down Expand Up @@ -152,14 +156,13 @@ export class RequestHandlerHelper {
}
}

protected endResponse_(negotiateMimeType: MIME_TYPE) {

const data = getResultBasedOnMiMe(negotiateMimeType,
protected endResponse_(negotiateMimeType: MIME_TYPE, shouldEvaluateData = true) {
const data = shouldEvaluateData ? getResultBasedOnMiMe(negotiateMimeType,
(this.controllerResult).responseData
, (type: MIME_TYPE) => {
negotiateMimeType = type;
}
);
) : "";

if (this.response.headersSent) {
console.trace("Request is finished, but triggered again");
Expand Down Expand Up @@ -204,9 +207,9 @@ export class RequestHandlerHelper {
{
const contentType = result.contentType || MIME_TYPE.Text;
switch (this.request.method) {
case HTTP_METHOD.Options:
case HTTP_METHOD.Head:
return this.endResponse_(contentType);
case HTTP_METHOD.Options:
return this.endResponse_(contentType, false);
}
const negotiateMimeType = this.getContentTypeFromNegotiation(contentType) as MIME_TYPE;
if (negotiateMimeType != null) {
Expand Down
9 changes: 6 additions & 3 deletions src/providers/post_data_evaluator_guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ export class PostDataEvaluatorGuard extends Guard {
}

async handlePostData() {
if (this.request.method === HTTP_METHOD.Get) {
return [new FileManager({}), {}];
switch (this.request.method) {
case HTTP_METHOD.Get:
case HTTP_METHOD.Delete:
case HTTP_METHOD.Head:
return [new FileManager({}), {}];
}
return this.parsePostData();
}
Expand Down Expand Up @@ -96,4 +99,4 @@ export class PostDataEvaluatorGuard extends Guard {
return [new FileManager({}), postData];
}
}
}
}
30 changes: 15 additions & 15 deletions tests/general/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/general/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"devDependencies": {
"@types/jest": "^24.0.15",
"@types/node": "^18.18.0",
"axios": "^1.6.3",
"axios": "^1.7.7",
"cross-env": "^5.2.0",
"jest": "^29.5.0",
"nodemon": "^3.0.1",
Expand Down
9 changes: 7 additions & 2 deletions tests/general/src/controllers/home_controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Controller, viewResult, worker, asQuery, asParam, HTTP_METHOD, route, jsonResult, htmlResult, textResult, defaultWorker, redirectResult, singleton } from "fortjs";
import { Controller, viewResult, worker, asQuery, asParam, HTTP_METHOD, route, jsonResult, htmlResult, textResult, defaultWorker, redirectResult, singleton, http } from "fortjs";
import { UserService } from "../services/user_service";
import { MySingleton } from "../extra/singleton";
import { StudentService } from "../services/student_service";
Expand Down Expand Up @@ -72,6 +72,11 @@ export class HomeController extends Controller {
});
}

@http.option("/html")
async htmlOptionRequest() {
return htmlResult(`<h1>hey there i am html</h1>`)
}

@worker(HTTP_METHOD.Post)
post() {
console.log("body", this.body, 'type', typeof this.body);
Expand Down Expand Up @@ -133,4 +138,4 @@ export class HomeController extends Controller {
query: qry
});
}
}
}
39 changes: 37 additions & 2 deletions tests/general/tests/e2e/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,32 @@ describe("/home", () => {
'Content-Type': 'application/json'
}
});
expect(res.headers['content-type']).toBe('application/json');
expect(res.data).toEqual({ "key": "hello", "value": "world" }); // Use 'data' property instead of 'text'
});

it('/json with head request', async () => {
const res: AxiosResponse<any> = await request.head('/home/json', {
headers: {
'Content-Type': 'application/json'
}
});
expect(res.status).toBe(200);
expect(res.headers['content-type']).toBe('application/json');
expect(res.data).toEqual(""); // Use 'data' property instead of 'text'
});

it('/json with options request', async () => {
const res: AxiosResponse<any> = await request.options('/home/json', {
headers: {
'Content-Type': 'application/json'
}
});
expect(res.status).toBe(200);
expect(res.headers['content-type']).toBe('text/plain');
expect(res.data).toEqual(""); // Use 'data' property instead of 'text'
});

it('/html', async () => {
const res: AxiosResponse<any> = await request.get('/home/html', {
headers: {
Expand All @@ -37,6 +60,18 @@ describe("/home", () => {
expect(res.data).toBe('<h1>hey there i am html</h1>'); // Use 'data' property instead of 'text'
});

it('/html option', async () => {
const res: AxiosResponse<any> = await request.options('/home/html', {
headers: {
'Accept': browserAccept
}
});
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toBe('text/html');
expect(res.data).toEqual("");
});


it('/text', async () => {
const res: AxiosResponse<any> = await request.get('/home/text');
expect(res.headers['content-type']).toBe('text/plain');
Expand All @@ -52,7 +87,7 @@ describe("/home", () => {
expect(res.status).toBe(405);
expect(res.headers['custom-header-from-outgoing-wall']).toBe('*');
expect(res.headers['content-type']).toBe('text/html');
expect(res.headers['allow']).toBe('GET');
expect(res.headers['allow']).toBe('GET,HEAD');
expect(res.data).toBe(methodNotAllowedMsg);
});

Expand Down Expand Up @@ -136,7 +171,7 @@ describe("/home", () => {
}
});
expect(res.status).toBe(200);
expect(res.headers['content-type']).toBe('text/html');
expect(res.headers['content-type']).toBe('text/plain');
expect(res.headers['custom-header-from-outgoing-wall']).toBe('*');
expect(res.headers['allow']).toBe('POST');
expect(res.data).toBe("");
Expand Down
2 changes: 1 addition & 1 deletion tests/general/tests/e2e/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ export * from "./injection";
export * from "./expect";
export * from "./routes";
export * from "./wall";
export * from "./cache";
export * from "./cache";
2 changes: 1 addition & 1 deletion tests/general/tests/e2e/random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe("/random", () => {

expect(res.status).toBe(406);
expect(res.headers['content-type']).toBe('application/xml');
expect(res.data).toEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><message>Not Acceptable.</message><url>/random/</url><status>406</status><method>GET</method><userAgent>axios/1.6.3</userAgent></root>");
expect(res.data).toEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><message>Not Acceptable.</message><url>/random/</url><status>406</status><method>GET</method><userAgent>axios/1.7.7</userAgent></root>");
});

it("/form", async () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/general/tests/e2e/wall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ describe("wall test", () => {
expect(res.headers['custom-header-from-incoming-wall']).toBe('*');
expect(res.headers['injection-result']).toBe('wall constructor onIncoming called on outgoing called');
expect(res.headers['wall-without-outgoing-wall']).toBe('*');
expect(res.data).toHaveProperty('reqCount', 130);
expect(res.data).toHaveProperty('reqCount', 133);
});
});

0 comments on commit c53ba5a

Please sign in to comment.