htmx-router
Advanced tools
Comparing version 1.0.4 to 1.0.5
@@ -56,6 +56,5 @@ import { QuickHash } from "./internal/util.js"; | ||
return null; | ||
const headers = new Headers(); | ||
headers.set("Content-Type", "text/css"); | ||
headers.set("Cache-Control", "public, max-age=604800"); | ||
return new Response(build.sheet, { headers }); | ||
ctx.headers.set("Content-Type", "text/css"); | ||
ctx.headers.set("Cache-Control", "public, max-age=604800"); | ||
return new Response(build.sheet, { headers: ctx.headers }); | ||
} |
import { ServerOnlyWarning } from "./internal/util.js"; | ||
ServerOnlyWarning("event-source"); | ||
// global for easy reuse | ||
const encoder = new TextEncoder(); | ||
const headers = new Headers(); | ||
// Chunked encoding with immediate forwarding by proxies (i.e. nginx) | ||
headers.set("X-Accel-Buffering", "no"); | ||
headers.set("Transfer-Encoding", "chunked"); | ||
headers.set("Content-Type", "text/event-stream"); | ||
// the maximum keep alive chrome shouldn't ignore | ||
headers.set("Keep-Alive", "timeout=120"); | ||
headers.set("Connection", "keep-alive"); | ||
/** | ||
@@ -98,11 +108,2 @@ * Helper for Server-Sent-Events, with auto close on SIGTERM and SIGHUP messages | ||
} | ||
// global for easy reuse | ||
const encoder = new TextEncoder(); | ||
const headers = new Headers(); | ||
// Chunked encoding with immediate forwarding by proxies (i.e. nginx) | ||
headers.set("X-Accel-Buffering", "no"); | ||
headers.set("Transfer-Encoding", "chunked"); | ||
headers.set("Content-Type", "text/event-stream"); | ||
headers.set("Keep-Alive", "timeout=120"); // the maximum keep alive chrome shouldn't ignore | ||
headers.set("Connection", "keep-alive"); | ||
// Auto close all SSE streams when shutdown requested | ||
@@ -109,0 +110,0 @@ // Without this graceful shutdowns will hang indefinitely |
@@ -123,6 +123,5 @@ import { ServerOnlyWarning } from "./util.js"; | ||
return null; | ||
const headers = new Headers(); | ||
headers.set("Content-Type", "text/javascript"); | ||
headers.set("Cache-Control", "public, max-age=604800"); | ||
return new Response(script, { headers }); | ||
ctx.headers.set("Content-Type", "text/javascript"); | ||
ctx.headers.set("Cache-Control", "public, max-age=604800"); | ||
return new Response(script, { headers: ctx.headers }); | ||
} |
import type { IncomingMessage, ServerResponse } from "http"; | ||
import type { ViteDevServer } from "vite"; | ||
import type { GenericContext } from "../router.js"; | ||
import { GenericContext } from "../router.js"; | ||
type Config = { | ||
@@ -5,0 +5,0 @@ build: Promise<any> | (() => Promise<Record<string, any>>); |
import type { Config } from './index.js'; | ||
import type { RouteTree } from '../../router.js'; | ||
export declare function createRequestHandler(config: Config): (req: Request) => Promise<Response>; | ||
export declare function createRequestHandler(config: Config): (req: Request) => Promise<{ | ||
response: Response; | ||
headers: { | ||
[key: string]: string | string[]; | ||
}; | ||
}>; | ||
export declare function Resolve(request: Request, tree: RouteTree, config: Config): Promise<{ | ||
@@ -5,0 +10,0 @@ response: Response; |
import { ServerOnlyWarning } from "../util.js"; | ||
ServerOnlyWarning("native-request"); | ||
import { GenericContext } from "../router.js"; | ||
import { MakeStatus } from "../../status.js"; | ||
export function createRequestHandler(config) { | ||
return async (req) => { | ||
try { | ||
const mod = typeof config.build === "function" ? await config.build() : await config.build; | ||
let { response } = await Resolve(req, mod.tree, config); | ||
return response; | ||
} | ||
catch (e) { | ||
if (e instanceof Error) { | ||
console.error(e.stack); | ||
config.viteDevServer?.ssrFixStacktrace(e); | ||
return new Response(e.message + "\n" + e.stack, { status: 500, statusText: "Internal Server Error" }); | ||
} | ||
else { | ||
console.error(e); | ||
return new Response(String(e), { status: 500, statusText: "Internal Server Error" }); | ||
} | ||
} | ||
const mod = typeof config.build === "function" ? await config.build() : await config.build; | ||
return await Resolve(req, mod.tree, config); | ||
}; | ||
} | ||
export async function Resolve(request, tree, config) { | ||
const url = new URL(request.url); | ||
const ctx = new GenericContext(request, url, config.render); | ||
const x = ctx.url.pathname.endsWith("/") ? ctx.url.pathname.slice(0, -1) : ctx.url.pathname; | ||
const fragments = x.split("/").slice(1); | ||
let response = await tree.resolve(fragments, ctx); | ||
if (response === null) | ||
response = new Response("No Route Found", { status: 404, statusText: "Not Found", headers: ctx.headers }); | ||
// Override with context headers | ||
if (response.headers !== ctx.headers) { | ||
for (const [key, value] of ctx.headers) { | ||
if (response.headers.has(key)) | ||
continue; | ||
response.headers.set(key, value); | ||
const ctx = new GenericContext(request, new URL(request.url), config.render); | ||
let response; | ||
try { | ||
const x = ctx.url.pathname.endsWith("/") ? ctx.url.pathname.slice(0, -1) : ctx.url.pathname; | ||
const fragments = x.split("/").slice(1); | ||
const res = await tree.resolve(fragments, ctx); | ||
response = res === null | ||
? new Response("No Route Found", MakeStatus("Not Found", ctx.headers)) | ||
: res; | ||
// Override with context headers | ||
if (response.headers !== ctx.headers) { | ||
for (const [key, value] of ctx.headers) | ||
response.headers.set(key, value); | ||
} | ||
} | ||
catch (e) { | ||
if (e instanceof Error) { | ||
console.error(e.stack); | ||
config.viteDevServer?.ssrFixStacktrace(e); | ||
response = new Response(e.message + "\n" + e.stack, { status: 500, statusText: "Internal Server Error" }); | ||
} | ||
else { | ||
console.error(e); | ||
response = new Response(String(e), { status: 500, statusText: "Internal Server Error" }); | ||
} | ||
} | ||
// Merge cookie changes | ||
@@ -41,0 +39,0 @@ const headers = Object.fromEntries(response.headers); |
{ | ||
"name": "htmx-router", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "A lightweight SSR framework with server+client islands", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -67,6 +67,3 @@ declare const definitions: { | ||
export type StatusText = typeof definitions[keyof typeof definitions]; | ||
export declare function MakeStatus(lookup: number | StatusText): { | ||
status: number; | ||
statusText: StatusText; | ||
}; | ||
export declare function MakeStatus(lookup: number | StatusText, init?: ResponseInit | Headers): ResponseInit; | ||
export {}; |
@@ -76,8 +76,10 @@ const definitions = { | ||
} | ||
export function MakeStatus(lookup) { | ||
export function MakeStatus(lookup, init) { | ||
if (init instanceof Headers) | ||
init = { headers: init }; | ||
if (typeof lookup === "number") | ||
return lookupCode(lookup); | ||
return lookupStatus(lookup); | ||
return lookupCode(lookup, init); | ||
return lookupStatus(lookup, init); | ||
} | ||
function lookupCode(status) { | ||
function lookupCode(status, init) { | ||
if (status < 100) | ||
@@ -87,9 +89,18 @@ throw new TypeError(`Status ${status}<100`); | ||
throw new TypeError(`Status ${status}>599`); | ||
return { status, statusText: lookup[status] }; | ||
const statusText = lookup[status]; | ||
return Status(status, statusText, init); | ||
} | ||
function lookupStatus(statusText) { | ||
function lookupStatus(statusText, init) { | ||
const status = index.get(statusText.toLowerCase()); | ||
if (!status) | ||
throw new TypeError(`statusText ${statusText} is not of type StatusText`); | ||
return Status(status, statusText, init); | ||
} | ||
function Status(status, statusText, init) { | ||
if (init) { | ||
init.statusText = statusText; | ||
init.status = status; | ||
return init; | ||
} | ||
return { status, statusText }; | ||
} |
81679
2358