136 lines
3.3 KiB
TypeScript
136 lines
3.3 KiB
TypeScript
import express from "express"
|
|
import fs from "fs/promises"
|
|
import { status } from "http-status"
|
|
import { createServer as createViteServer } from "vite"
|
|
import { injectIntoHtml } from "./src/utils/inject"
|
|
import { partials } from "./src/plugins/injectPartials"
|
|
|
|
const app = express()
|
|
|
|
const vite = await createViteServer({
|
|
server: { middlewareMode: true },
|
|
appType: "mpa",
|
|
})
|
|
|
|
app.use(express.urlencoded({ extended: true }))
|
|
app.use(express.json())
|
|
|
|
// Log every incoming request to the terminal
|
|
app.use((req, res, next) => {
|
|
console.log("\n" + "=".repeat(50))
|
|
console.log(`${req.method} ${req.url}`)
|
|
console.log("\n-- Headers --")
|
|
console.log(req.headers)
|
|
if (Object.keys(req.body || {}).length > 0) {
|
|
console.log("\n-- Body --")
|
|
console.log(req.body)
|
|
}
|
|
if (Object.keys(req.cookies || {}).length > 0) {
|
|
console.log("\n-- Cookies --")
|
|
console.log(req.cookies)
|
|
}
|
|
console.log("=".repeat(50))
|
|
next()
|
|
})
|
|
|
|
// Receives the POST: echoes the body back
|
|
app.post("/login", async (req, res) => {
|
|
const { username, password } = req.body
|
|
const base = await fs.readFile("src/partials/form-response.html", "utf-8")
|
|
|
|
let result = await injectIntoHtml(base, [
|
|
...partials,
|
|
{
|
|
key: "<!--LOGIN_DATA-->",
|
|
placement: "replace",
|
|
type: "string",
|
|
value: JSON.stringify({ username, password }, null, 2),
|
|
},
|
|
])
|
|
|
|
res.send(result)
|
|
})
|
|
|
|
// Sets a cookie: shows Set-Cookie header in DevTools
|
|
app.get("/set-cookie", (req, res) => {
|
|
res.cookie("session", "abc123xyz", {
|
|
httpOnly: true,
|
|
maxAge: 60 * 60 * 1000, // 1 hour
|
|
})
|
|
req.next?.()
|
|
})
|
|
|
|
// Shows what cookies the server received
|
|
app.get("/show-cookies", async (req, res) => {
|
|
const cookieHeader = req.headers["cookie"] || "none"
|
|
const base = await fs.readFile("show-cookie.html", "utf-8")
|
|
|
|
let result = await injectIntoHtml(base, [
|
|
...partials,
|
|
{
|
|
key: "<!--COOKIES-->",
|
|
placement: "replace",
|
|
type: "string",
|
|
value: cookieHeader,
|
|
},
|
|
])
|
|
|
|
res.send(result)
|
|
})
|
|
|
|
// Returns JSON: shows Content-Type in action
|
|
app.get("/json", (req, res) => {
|
|
res.json({
|
|
message: "This is a JSON response",
|
|
method: req.method,
|
|
url: req.url,
|
|
headers: req.headers,
|
|
})
|
|
})
|
|
|
|
// Delayed response: simulates a slow server
|
|
app.get("/delay", (req, res) => {
|
|
setTimeout(() => {
|
|
req.next?.()
|
|
}, 5000)
|
|
})
|
|
|
|
// Demonstrates different status codes
|
|
app.get("/status/:code", async (req, res) => {
|
|
const code = parseInt(req.params.code)
|
|
const base = await fs.readFile("status-code.html", "utf-8")
|
|
|
|
let result = await injectIntoHtml(base, [
|
|
...partials,
|
|
{
|
|
key: "<!--HTTP_STATUS_CODE-->",
|
|
placement: "replace",
|
|
type: "string",
|
|
value: code.toString(),
|
|
occurrence: "all",
|
|
},
|
|
{
|
|
key: "<!--HTTP_STATUS_NAME-->",
|
|
placement: "replace",
|
|
type: "string",
|
|
value: String(status[code as keyof typeof status]),
|
|
occurrence: "all",
|
|
},
|
|
{
|
|
key: "<!--HTTP_HEADERS-->",
|
|
placement: "replace",
|
|
type: "string",
|
|
value: JSON.stringify(req.headers, null, 2),
|
|
occurrence: "all",
|
|
},
|
|
])
|
|
|
|
res.status(code).send(result)
|
|
})
|
|
|
|
app.use(vite.middlewares)
|
|
|
|
app.listen(3000, () => {
|
|
console.log("Echo server running on http://localhost:3000")
|
|
console.log("Watching for requests...\n")
|
|
})
|