Skip to content

Commit 7f9a5e9

Browse files
jamieecarrasquilloJonathanRosado
authored andcommitted
initial commit
1 parent 0e23c9e commit 7f9a5e9

File tree

17 files changed

+996
-0
lines changed

17 files changed

+996
-0
lines changed

.gitignore

Whitespace-only changes.

.idea/.gitignore

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/codeStyles/codeStyleConfig.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/deno-experiments.iml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/deno.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

application.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { serve, ServeInit } from "https://deno.land/[email protected]/http/server.ts";
2+
import { Handler } from "./handler.ts";
3+
import {CatchFunc, HandleFunc, Matcher} from "./types.ts";
4+
import { Request as RoarterRequest } from "./request.ts";
5+
6+
export class Application {
7+
handlers: Handler[] = [];
8+
catchFunc: CatchFunc = () => {
9+
throw new Error("Not Implemented");
10+
};
11+
12+
match(custom: Matcher): Handler {
13+
const handler = new Handler().match(custom);
14+
this.handlers.push(handler);
15+
return handler;
16+
}
17+
18+
get get(): Handler {
19+
const handler = new Handler().get;
20+
this.handlers.push(handler);
21+
return handler;
22+
}
23+
24+
get post(): Handler {
25+
const handler = new Handler().post;
26+
this.handlers.push(handler);
27+
return handler;
28+
}
29+
30+
get put(): Handler {
31+
const handler = new Handler().put;
32+
this.handlers.push(handler);
33+
return handler;
34+
}
35+
36+
get delete(): Handler {
37+
const handler = new Handler().delete;
38+
this.handlers.push(handler);
39+
return handler;
40+
}
41+
42+
get patch(): Handler {
43+
const handler = new Handler().patch;
44+
this.handlers.push(handler);
45+
return handler;
46+
}
47+
48+
path(path: string): Handler {
49+
const handler = new Handler().path(path);
50+
this.handlers.push(handler);
51+
return handler;
52+
}
53+
54+
queries(queries: string[]): Handler {
55+
const handler = new Handler().queries(queries);
56+
this.handlers.push(handler);
57+
return handler;
58+
}
59+
60+
handle(handler: HandleFunc | Application): Handler {
61+
const h = new Handler().handle(handler);
62+
this.handlers.push(h);
63+
return h;
64+
}
65+
66+
catch(fn: CatchFunc) {
67+
this.catchFunc = fn;
68+
}
69+
70+
// Handler runs all the registered handlers and returns the first
71+
// response it finds. After returning the first response, it runs
72+
// the remaining handlers. The purpose of this is to support middleware
73+
// after a response has been sent.
74+
async runHandlers(req: RoarterRequest): Promise<Response> {
75+
let runRemaining = true
76+
let i = 0;
77+
try {
78+
try {
79+
for (i; i < this.handlers.length; i++) {
80+
const handler = this.handlers[i];
81+
const response = await handler.run(req);
82+
if (response) {
83+
i++;
84+
return response;
85+
}
86+
}
87+
} catch (e) {
88+
// If an error occurs, we wan't to skip all handlers and run the catchFunc
89+
runRemaining = false
90+
return await this.catchFunc(req, e);
91+
}
92+
// If after running all the handlers there is no response, throw the error
93+
throw new Error(
94+
`No Response was sent for ${req.method} ${req.url}`,
95+
);
96+
} finally {
97+
if (runRemaining) {
98+
// Since at this point we have already returned a response,
99+
// we run the remaining handlers ignoring their response and errors
100+
for (i; i < this.handlers.length; i++) {
101+
const handler = this.handlers[i];
102+
handler.run(req).catch(e => {
103+
this.catchFunc(req, e)
104+
})
105+
}
106+
}
107+
}
108+
}
109+
110+
async handler(domReq: Request): Promise<Response> {
111+
const req = new RoarterRequest(domReq);
112+
return this.runHandlers(req)
113+
}
114+
115+
async serve(options?: ServeInit) {
116+
this.handler = this.handler.bind(this);
117+
await serve(this.handler, options);
118+
}
119+
}

handler.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { HandleFunc, Matcher } from "./types.ts";
2+
import {
3+
buildPathMatcher,
4+
buildQueryMatcher,
5+
deleteMatcher,
6+
getMatcher,
7+
patchMatcher,
8+
postMatcher,
9+
putMatcher,
10+
} from "./matchers.ts";
11+
import { Response } from "./response.ts";
12+
import { Request } from "./request.ts";
13+
import {Application} from "./application.ts";
14+
15+
export class Handler {
16+
matchers: Matcher[] = [];
17+
handler: (HandleFunc | Application) | null = null;
18+
19+
private isHandlerASubRouter(): boolean {
20+
return this.handler instanceof Application
21+
}
22+
23+
runMatchers(req: Request): boolean {
24+
for (let i = 0; i < this.matchers.length; i++) {
25+
const matcher: Matcher = this.matchers[i];
26+
if (!matcher(req, this.isHandlerASubRouter())) return false;
27+
}
28+
return true;
29+
}
30+
31+
async runHandler(req: Request) {
32+
if (!this.handler) return;
33+
if (this.isHandlerASubRouter()) {
34+
return (this.handler as Application).runHandlers(req)
35+
} else {
36+
return (this.handler as HandleFunc)(req);
37+
}
38+
}
39+
40+
match(custom: Matcher): Handler {
41+
this.matchers.push(custom);
42+
return this;
43+
}
44+
45+
get get(): Handler {
46+
return this.match(getMatcher);
47+
}
48+
49+
get post(): Handler {
50+
return this.match(postMatcher);
51+
}
52+
53+
get put(): Handler {
54+
return this.match(putMatcher);
55+
}
56+
57+
get delete(): Handler {
58+
return this.match(deleteMatcher);
59+
}
60+
61+
get patch(): Handler {
62+
return this.match(patchMatcher);
63+
}
64+
65+
path(urlPath: string): Handler {
66+
return this.match(buildPathMatcher(urlPath));
67+
}
68+
69+
queries(queries: string[]): Handler {
70+
return this.match(buildQueryMatcher(queries));
71+
}
72+
73+
handle(handler: HandleFunc | Application) {
74+
this.handler = handler;
75+
return this;
76+
}
77+
78+
async run(req: Request) {
79+
if (this.runMatchers(req)) {
80+
return this.runHandler(req);
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)