-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Ole Herman Schumacher Elgesem <[email protected]>
- Loading branch information
1 parent
23f935d
commit 0607845
Showing
17 changed files
with
314 additions
and
331 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,9 @@ | ||
# Towers | ||
# trpg | ||
|
||
https://towers.oleherman.com | ||
|
||
## Development server | ||
|
||
Start the development server: | ||
https://trpg.oleherman.com | ||
|
||
``` | ||
node server.js | ||
docker build --tag trpg . && docker run -it -p 3000:3000 --name trpg --rm trpg | ||
``` | ||
|
||
For development purposes it defaults to port 3000: | ||
|
||
http://127.0.0.1:3000 | ||
|
||
## Containers | ||
|
||
### docker | ||
|
||
``` | ||
docker build --tag towers . && docker run -it -p 3000:3000 --name towers --rm towers | ||
``` | ||
|
||
http://127.0.0.1:80 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,92 @@ | ||
// Start listening on port 3000 of localhost. | ||
const server = Deno.listen({ port: 3000 }); | ||
console.log("Backend running on http://localhost:3000/"); | ||
|
||
for await (const conn of server) { | ||
handleHttp(conn).catch(console.error); | ||
} | ||
|
||
function illegalURL(path) { | ||
return ( | ||
!path.startsWith("/") || | ||
path.includes("..") || | ||
path.includes("//") || | ||
path.includes(" ") || | ||
path.includes(";") || | ||
path.includes(",") || | ||
path.includes("'") || | ||
path.includes('"') || | ||
path.includes("*") | ||
); | ||
} | ||
|
||
function getContentType(path: string): string { | ||
if (path === "/index.html") { | ||
return "text/html"; | ||
} | ||
if (path === "/favicon.ico") { | ||
return "image/x-icon"; | ||
} | ||
if (path.endsWith(".js")) { | ||
return "application/javascript"; | ||
} | ||
if (path.endsWith(".css")) { | ||
return "text/css"; | ||
} | ||
return ""; | ||
} | ||
|
||
async function notFound(requestEvent) { | ||
const notFoundResponse = new Response("404 Not Found", { status: 404 }); | ||
await requestEvent.respondWith(notFoundResponse); | ||
} | ||
|
||
async function handleAPI(requestEvent) { | ||
await notFound(requestEvent); | ||
} | ||
|
||
async function handleFile(requestEvent, filepath) { | ||
if (filepath === "/") { | ||
filepath = "/index.html"; | ||
} | ||
|
||
const contentType: string = getContentType(filepath); | ||
if (contentType === "") { | ||
await notFound(requestEvent); | ||
return; | ||
} | ||
|
||
// Try opening the file | ||
let file; | ||
try { | ||
file = await Deno.open(`./dist${filepath}`, { read: true }); | ||
} catch { | ||
await notFound(requestEvent); | ||
return; | ||
} | ||
|
||
const readableStream = file.readable; | ||
const headers: HeadersInit = { "content-type": contentType }; | ||
const response = new Response(readableStream, { headers: headers }); | ||
await requestEvent.respondWith(response); | ||
return; | ||
} | ||
|
||
async function handleHttp(conn: Deno.Conn) { | ||
const httpConn = Deno.serveHttp(conn); | ||
for await (const requestEvent of httpConn) { | ||
const url = new URL(requestEvent.request.url); | ||
let filepath = decodeURIComponent(url.pathname); | ||
|
||
if (illegalURL(filepath)) { | ||
await notFound(requestEvent); | ||
continue; | ||
} | ||
if (filepath.startsWith("/api/")) { | ||
await handleAPI(requestEvent, filepath); | ||
continue; | ||
} | ||
|
||
await handleFile(requestEvent, filepath); | ||
} | ||
} | ||
// Start listening on port 3000 of localhost. | ||
const server = Deno.listen({ port: 3000 }); | ||
console.log("Backend running on http://localhost:3000/"); | ||
|
||
for await (const conn of server) { | ||
handleHttp(conn).catch(console.error); | ||
} | ||
|
||
function illegalURL(path) { | ||
return ( | ||
!path.startsWith("/") || | ||
path.includes("..") || | ||
path.includes("//") || | ||
path.includes(" ") || | ||
path.includes(";") || | ||
path.includes(",") || | ||
path.includes("'") || | ||
path.includes('"') || | ||
path.includes("*") | ||
); | ||
} | ||
|
||
function getContentType(path: string): string { | ||
if (path === "/index.html") { | ||
return "text/html"; | ||
} | ||
if (path === "/favicon.ico") { | ||
return "image/x-icon"; | ||
} | ||
if (path.endsWith(".js")) { | ||
return "application/javascript"; | ||
} | ||
if (path.endsWith(".css")) { | ||
return "text/css"; | ||
} | ||
return ""; | ||
} | ||
|
||
async function notFound(requestEvent) { | ||
const notFoundResponse = new Response("404 Not Found", { status: 404 }); | ||
await requestEvent.respondWith(notFoundResponse); | ||
} | ||
|
||
async function handleAPI(requestEvent) { | ||
await notFound(requestEvent); | ||
} | ||
|
||
async function handleFile(requestEvent, filepath) { | ||
if (filepath === "/") { | ||
filepath = "/index.html"; | ||
} | ||
|
||
const contentType: string = getContentType(filepath); | ||
if (contentType === "") { | ||
await notFound(requestEvent); | ||
return; | ||
} | ||
|
||
// Try opening the file | ||
let file; | ||
try { | ||
file = await Deno.open(`./dist${filepath}`, { read: true }); | ||
} catch { | ||
await notFound(requestEvent); | ||
return; | ||
} | ||
|
||
const readableStream = file.readable; | ||
const headers: HeadersInit = { "content-type": contentType }; | ||
const response = new Response(readableStream, { headers: headers }); | ||
await requestEvent.respondWith(response); | ||
return; | ||
} | ||
|
||
async function handleHttp(conn: Deno.Conn) { | ||
const httpConn = Deno.serveHttp(conn); | ||
for await (const requestEvent of httpConn) { | ||
const url = new URL(requestEvent.request.url); | ||
let filepath = decodeURIComponent(url.pathname); | ||
|
||
if (illegalURL(filepath)) { | ||
await notFound(requestEvent); | ||
continue; | ||
} | ||
if (filepath.startsWith("/api/")) { | ||
await handleAPI(requestEvent, filepath); | ||
continue; | ||
} | ||
|
||
await handleFile(requestEvent, filepath); | ||
} | ||
} |
Oops, something went wrong.