Comparing version 4.5.11 to 4.6.0
@@ -17,3 +17,3 @@ // src/adapter/cloudflare-pages/handler.ts | ||
const context = new Context(executionCtx.request, { | ||
env: executionCtx.env, | ||
env: { ...executionCtx.env, eventContext: executionCtx }, | ||
executionCtx | ||
@@ -20,0 +20,0 @@ }); |
@@ -41,3 +41,3 @@ "use strict"; | ||
const context = new import_context.Context(executionCtx.request, { | ||
env: executionCtx.env, | ||
env: { ...executionCtx.env, eventContext: executionCtx }, | ||
executionCtx | ||
@@ -44,0 +44,0 @@ }); |
@@ -85,12 +85,26 @@ "use strict"; | ||
if (this.#res && _res) { | ||
this.#res.headers.delete("content-type"); | ||
for (const [k, v] of this.#res.headers.entries()) { | ||
if (k === "set-cookie") { | ||
const cookies = this.#res.headers.getSetCookie(); | ||
_res.headers.delete("set-cookie"); | ||
for (const cookie of cookies) { | ||
_res.headers.append("set-cookie", cookie); | ||
try { | ||
for (const [k, v] of this.#res.headers.entries()) { | ||
if (k === "content-type") { | ||
continue; | ||
} | ||
if (k === "set-cookie") { | ||
const cookies = this.#res.headers.getSetCookie(); | ||
_res.headers.delete("set-cookie"); | ||
for (const cookie of cookies) { | ||
_res.headers.append("set-cookie", cookie); | ||
} | ||
} else { | ||
_res.headers.set(k, v); | ||
} | ||
} | ||
} catch (e) { | ||
if (e instanceof TypeError && e.message.includes("immutable")) { | ||
this.res = new Response(_res.body, { | ||
headers: _res.headers, | ||
status: _res.status | ||
}); | ||
return; | ||
} else { | ||
_res.headers.set(k, v); | ||
throw e; | ||
} | ||
@@ -239,10 +253,5 @@ } | ||
if (typeof html === "object") { | ||
if (!(html instanceof Promise)) { | ||
html = html.toString(); | ||
} | ||
if (html instanceof Promise) { | ||
return html.then((html2) => (0, import_html.resolveCallback)(html2, import_html.HtmlEscapedCallbackPhase.Stringify, false, {})).then((html2) => { | ||
return typeof arg === "number" ? this.newResponse(html2, arg, headers) : this.newResponse(html2, arg); | ||
}); | ||
} | ||
return (0, import_html.resolveCallback)(html, import_html.HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => { | ||
return typeof arg === "number" ? this.newResponse(html2, arg, headers) : this.newResponse(html2, arg); | ||
}); | ||
} | ||
@@ -249,0 +258,0 @@ return typeof arg === "number" ? this.newResponse(html, arg, headers) : this.newResponse(html, arg); |
@@ -26,2 +26,3 @@ "use strict"; | ||
var import_stream = require("../../utils/stream"); | ||
var import_html = require("../../utils/html"); | ||
class SSEStreamingApi extends import_stream.StreamingApi { | ||
@@ -32,3 +33,4 @@ constructor(writable, readable) { | ||
async writeSSE(message) { | ||
const data = message.data.split("\n").map((line) => { | ||
const data = await (0, import_html.resolveCallback)(message.data, import_html.HtmlEscapedCallbackPhase.Stringify, false, {}); | ||
const dataLines = data.split("\n").map((line) => { | ||
return `data: ${line}`; | ||
@@ -38,3 +40,3 @@ }).join("\n"); | ||
message.event && `event: ${message.event}`, | ||
data, | ||
dataLines, | ||
message.id && `id: ${message.id}`, | ||
@@ -41,0 +43,0 @@ message.retry && `retry: ${message.retry}` |
@@ -38,2 +38,5 @@ "use strict"; | ||
} | ||
if (!options.invalidUserMessage) { | ||
options.invalidUserMessage = "Unauthorized"; | ||
} | ||
if (usernamePasswordInOptions) { | ||
@@ -63,9 +66,15 @@ users.unshift({ username: options.username, password: options.password }); | ||
} | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
const status = 401; | ||
const headers = { | ||
"WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"' | ||
}; | ||
const responseMessage = typeof options.invalidUserMessage === "function" ? await options.invalidUserMessage(ctx) : options.invalidUserMessage; | ||
const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), { | ||
status, | ||
headers: { | ||
"WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"' | ||
...headers, | ||
"content-type": "application/json; charset=UTF-8" | ||
} | ||
}); | ||
throw new import_http_exception.HTTPException(401, { res }); | ||
throw new import_http_exception.HTTPException(status, { res }); | ||
}; | ||
@@ -72,0 +81,0 @@ }; |
@@ -43,22 +43,34 @@ "use strict"; | ||
const wwwAuthenticatePrefix = options.prefix === "" ? "" : `${options.prefix} `; | ||
const throwHTTPException = async (c, status, wwwAuthenticateHeader, messageOption) => { | ||
const headers = { | ||
"WWW-Authenticate": wwwAuthenticateHeader | ||
}; | ||
const responseMessage = typeof messageOption === "function" ? await messageOption(c) : messageOption; | ||
const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), { | ||
status, | ||
headers: { | ||
...headers, | ||
"content-type": "application/json; charset=UTF-8" | ||
} | ||
}); | ||
throw new import_http_exception.HTTPException(status, { res }); | ||
}; | ||
return async function bearerAuth2(c, next) { | ||
const headerToken = c.req.header(options.headerName || HEADER); | ||
if (!headerToken) { | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}realm="` + realm + '"' | ||
} | ||
}); | ||
throw new import_http_exception.HTTPException(401, { res }); | ||
await throwHTTPException( | ||
c, | ||
401, | ||
`${wwwAuthenticatePrefix}realm="${realm}"`, | ||
options.noAuthenticationHeaderMessage || "Unauthorized" | ||
); | ||
} else { | ||
const match = regexp.exec(headerToken); | ||
if (!match) { | ||
const res = new Response("Bad Request", { | ||
status: 400, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}error="invalid_request"` | ||
} | ||
}); | ||
throw new import_http_exception.HTTPException(400, { res }); | ||
await throwHTTPException( | ||
c, | ||
400, | ||
`${wwwAuthenticatePrefix}error="invalid_request"`, | ||
options.invalidAuthenticationHeaderMessage || "Bad Request" | ||
); | ||
} else { | ||
@@ -79,9 +91,8 @@ let equal = false; | ||
if (!equal) { | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}error="invalid_token"` | ||
} | ||
}); | ||
throw new import_http_exception.HTTPException(401, { res }); | ||
await throwHTTPException( | ||
c, | ||
401, | ||
`${wwwAuthenticatePrefix}error="invalid_token"`, | ||
options.invalidTokenMessage || "Unauthorized" | ||
); | ||
} | ||
@@ -88,0 +99,0 @@ } |
@@ -48,2 +48,3 @@ "use strict"; | ||
c.header("Content-Type", "text/html; charset=UTF-8"); | ||
c.header("Content-Encoding", "Identity"); | ||
} else { | ||
@@ -50,0 +51,0 @@ for (const [key, value] of Object.entries(options.stream)) { |
@@ -53,3 +53,4 @@ "use strict"; | ||
xXssProtection: true, | ||
removePoweredBy: true | ||
removePoweredBy: true, | ||
permissionsPolicy: {} | ||
}; | ||
@@ -80,2 +81,8 @@ const generateNonce = () => { | ||
} | ||
if (options.permissionsPolicy && Object.keys(options.permissionsPolicy).length > 0) { | ||
headersToSet.push([ | ||
"Permissions-Policy", | ||
getPermissionsPolicyDirectives(options.permissionsPolicy) | ||
]); | ||
} | ||
if (options.reportingEndpoints) { | ||
@@ -140,2 +147,24 @@ headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]); | ||
} | ||
function getPermissionsPolicyDirectives(policy) { | ||
return Object.entries(policy).map(([directive, value]) => { | ||
const kebabDirective = camelToKebab(directive); | ||
if (typeof value === "boolean") { | ||
return `${kebabDirective}=${value ? "*" : "none"}`; | ||
} | ||
if (Array.isArray(value)) { | ||
if (value.length === 0) { | ||
return `${kebabDirective}=()`; | ||
} | ||
if (value.length === 1 && (value[0] === "*" || value[0] === "none")) { | ||
return `${kebabDirective}=${value[0]}`; | ||
} | ||
const allowlist = value.map((item) => ["self", "src"].includes(item) ? item : `"${item}"`); | ||
return `${kebabDirective}=(${allowlist.join(" ")})`; | ||
} | ||
return ""; | ||
}).filter(Boolean).join(", "); | ||
} | ||
function camelToKebab(str) { | ||
return str.replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase(); | ||
} | ||
function getReportingEndpoints(reportingEndpoints = []) { | ||
@@ -142,0 +171,0 @@ return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", "); |
@@ -26,2 +26,7 @@ "use strict"; | ||
var import_mime = require("../../utils/mime"); | ||
const ENCODINGS = { | ||
br: ".br", | ||
zstd: ".zst", | ||
gzip: ".gz" | ||
}; | ||
const DEFAULT_DOCUMENT = "index.html"; | ||
@@ -44,3 +49,3 @@ const defaultPathResolve = (path) => path; | ||
if (path2 && await options.isDir(path2)) { | ||
filename = filename + "/"; | ||
filename += "/"; | ||
} | ||
@@ -61,14 +66,14 @@ } | ||
if (!content) { | ||
let pathWithOutDefaultDocument = (0, import_filepath.getFilePathWithoutDefaultDocument)({ | ||
let pathWithoutDefaultDocument = (0, import_filepath.getFilePathWithoutDefaultDocument)({ | ||
filename, | ||
root | ||
}); | ||
if (!pathWithOutDefaultDocument) { | ||
if (!pathWithoutDefaultDocument) { | ||
return await next(); | ||
} | ||
pathWithOutDefaultDocument = pathResolve(pathWithOutDefaultDocument); | ||
if (pathWithOutDefaultDocument !== path) { | ||
content = await getContent(pathWithOutDefaultDocument, c); | ||
pathWithoutDefaultDocument = pathResolve(pathWithoutDefaultDocument); | ||
if (pathWithoutDefaultDocument !== path) { | ||
content = await getContent(pathWithoutDefaultDocument, c); | ||
if (content) { | ||
path = pathWithOutDefaultDocument; | ||
path = pathWithoutDefaultDocument; | ||
} | ||
@@ -80,12 +85,24 @@ } | ||
} | ||
const mimeType = options.mimes ? (0, import_mime.getMimeType)(path, options.mimes) ?? (0, import_mime.getMimeType)(path) : (0, import_mime.getMimeType)(path); | ||
if (mimeType) { | ||
c.header("Content-Type", mimeType); | ||
} | ||
if (content) { | ||
let mimeType; | ||
if (options.mimes) { | ||
mimeType = (0, import_mime.getMimeType)(path, options.mimes) ?? (0, import_mime.getMimeType)(path); | ||
} else { | ||
mimeType = (0, import_mime.getMimeType)(path); | ||
if (options.precompressed) { | ||
const acceptEncodings = c.req.header("Accept-Encoding")?.split(",").map((encoding) => encoding.trim()).filter( | ||
(encoding) => Object.hasOwn(ENCODINGS, encoding) | ||
).sort( | ||
(a, b) => Object.keys(ENCODINGS).indexOf(a) - Object.keys(ENCODINGS).indexOf(b) | ||
) ?? []; | ||
for (const encoding of acceptEncodings) { | ||
const compressedContent = await getContent(path + ENCODINGS[encoding], c); | ||
if (compressedContent) { | ||
content = compressedContent; | ||
c.header("Content-Encoding", encoding); | ||
c.header("Vary", "Accept-Encoding", { append: true }); | ||
break; | ||
} | ||
} | ||
} | ||
if (mimeType) { | ||
c.header("Content-Type", mimeType); | ||
} | ||
await options.onFound?.(path, c); | ||
return c.body(content); | ||
@@ -92,0 +109,0 @@ } |
@@ -115,2 +115,10 @@ "use strict"; | ||
const resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => { | ||
if (typeof str === "object" && !(str instanceof String)) { | ||
if (!(str instanceof Promise)) { | ||
str = str.toString(); | ||
} | ||
if (str instanceof Promise) { | ||
str = await str; | ||
} | ||
} | ||
const callbacks = str.callbacks; | ||
@@ -117,0 +125,0 @@ if (!callbacks?.length) { |
@@ -62,12 +62,26 @@ // src/context.ts | ||
if (this.#res && _res) { | ||
this.#res.headers.delete("content-type"); | ||
for (const [k, v] of this.#res.headers.entries()) { | ||
if (k === "set-cookie") { | ||
const cookies = this.#res.headers.getSetCookie(); | ||
_res.headers.delete("set-cookie"); | ||
for (const cookie of cookies) { | ||
_res.headers.append("set-cookie", cookie); | ||
try { | ||
for (const [k, v] of this.#res.headers.entries()) { | ||
if (k === "content-type") { | ||
continue; | ||
} | ||
if (k === "set-cookie") { | ||
const cookies = this.#res.headers.getSetCookie(); | ||
_res.headers.delete("set-cookie"); | ||
for (const cookie of cookies) { | ||
_res.headers.append("set-cookie", cookie); | ||
} | ||
} else { | ||
_res.headers.set(k, v); | ||
} | ||
} | ||
} catch (e) { | ||
if (e instanceof TypeError && e.message.includes("immutable")) { | ||
this.res = new Response(_res.body, { | ||
headers: _res.headers, | ||
status: _res.status | ||
}); | ||
return; | ||
} else { | ||
_res.headers.set(k, v); | ||
throw e; | ||
} | ||
@@ -216,10 +230,5 @@ } | ||
if (typeof html === "object") { | ||
if (!(html instanceof Promise)) { | ||
html = html.toString(); | ||
} | ||
if (html instanceof Promise) { | ||
return html.then((html2) => resolveCallback(html2, HtmlEscapedCallbackPhase.Stringify, false, {})).then((html2) => { | ||
return typeof arg === "number" ? this.newResponse(html2, arg, headers) : this.newResponse(html2, arg); | ||
}); | ||
} | ||
return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => { | ||
return typeof arg === "number" ? this.newResponse(html2, arg, headers) : this.newResponse(html2, arg); | ||
}); | ||
} | ||
@@ -226,0 +235,0 @@ return typeof arg === "number" ? this.newResponse(html, arg, headers) : this.newResponse(html, arg); |
// src/helper/streaming/sse.ts | ||
import { StreamingApi } from "../../utils/stream.js"; | ||
import { HtmlEscapedCallbackPhase, resolveCallback } from "../../utils/html.js"; | ||
var SSEStreamingApi = class extends StreamingApi { | ||
@@ -8,3 +9,4 @@ constructor(writable, readable) { | ||
async writeSSE(message) { | ||
const data = message.data.split("\n").map((line) => { | ||
const data = await resolveCallback(message.data, HtmlEscapedCallbackPhase.Stringify, false, {}); | ||
const dataLines = data.split("\n").map((line) => { | ||
return `data: ${line}`; | ||
@@ -14,3 +16,3 @@ }).join("\n"); | ||
message.event && `event: ${message.event}`, | ||
data, | ||
dataLines, | ||
message.id && `id: ${message.id}`, | ||
@@ -17,0 +19,0 @@ message.retry && `retry: ${message.retry}` |
@@ -16,2 +16,5 @@ // src/middleware/basic-auth/index.ts | ||
} | ||
if (!options.invalidUserMessage) { | ||
options.invalidUserMessage = "Unauthorized"; | ||
} | ||
if (usernamePasswordInOptions) { | ||
@@ -41,9 +44,15 @@ users.unshift({ username: options.username, password: options.password }); | ||
} | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
const status = 401; | ||
const headers = { | ||
"WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"' | ||
}; | ||
const responseMessage = typeof options.invalidUserMessage === "function" ? await options.invalidUserMessage(ctx) : options.invalidUserMessage; | ||
const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), { | ||
status, | ||
headers: { | ||
"WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"' | ||
...headers, | ||
"content-type": "application/json; charset=UTF-8" | ||
} | ||
}); | ||
throw new HTTPException(401, { res }); | ||
throw new HTTPException(status, { res }); | ||
}; | ||
@@ -50,0 +59,0 @@ }; |
@@ -21,22 +21,34 @@ // src/middleware/bearer-auth/index.ts | ||
const wwwAuthenticatePrefix = options.prefix === "" ? "" : `${options.prefix} `; | ||
const throwHTTPException = async (c, status, wwwAuthenticateHeader, messageOption) => { | ||
const headers = { | ||
"WWW-Authenticate": wwwAuthenticateHeader | ||
}; | ||
const responseMessage = typeof messageOption === "function" ? await messageOption(c) : messageOption; | ||
const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), { | ||
status, | ||
headers: { | ||
...headers, | ||
"content-type": "application/json; charset=UTF-8" | ||
} | ||
}); | ||
throw new HTTPException(status, { res }); | ||
}; | ||
return async function bearerAuth2(c, next) { | ||
const headerToken = c.req.header(options.headerName || HEADER); | ||
if (!headerToken) { | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}realm="` + realm + '"' | ||
} | ||
}); | ||
throw new HTTPException(401, { res }); | ||
await throwHTTPException( | ||
c, | ||
401, | ||
`${wwwAuthenticatePrefix}realm="${realm}"`, | ||
options.noAuthenticationHeaderMessage || "Unauthorized" | ||
); | ||
} else { | ||
const match = regexp.exec(headerToken); | ||
if (!match) { | ||
const res = new Response("Bad Request", { | ||
status: 400, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}error="invalid_request"` | ||
} | ||
}); | ||
throw new HTTPException(400, { res }); | ||
await throwHTTPException( | ||
c, | ||
400, | ||
`${wwwAuthenticatePrefix}error="invalid_request"`, | ||
options.invalidAuthenticationHeaderMessage || "Bad Request" | ||
); | ||
} else { | ||
@@ -57,9 +69,8 @@ let equal = false; | ||
if (!equal) { | ||
const res = new Response("Unauthorized", { | ||
status: 401, | ||
headers: { | ||
"WWW-Authenticate": `${wwwAuthenticatePrefix}error="invalid_token"` | ||
} | ||
}); | ||
throw new HTTPException(401, { res }); | ||
await throwHTTPException( | ||
c, | ||
401, | ||
`${wwwAuthenticatePrefix}error="invalid_token"`, | ||
options.invalidTokenMessage || "Unauthorized" | ||
); | ||
} | ||
@@ -66,0 +77,0 @@ } |
@@ -24,2 +24,3 @@ // src/middleware/jsx-renderer/index.ts | ||
c.header("Content-Type", "text/html; charset=UTF-8"); | ||
c.header("Content-Encoding", "Identity"); | ||
} else { | ||
@@ -26,0 +27,0 @@ for (const [key, value] of Object.entries(options.stream)) { |
@@ -30,3 +30,4 @@ // src/middleware/secure-headers/secure-headers.ts | ||
xXssProtection: true, | ||
removePoweredBy: true | ||
removePoweredBy: true, | ||
permissionsPolicy: {} | ||
}; | ||
@@ -57,2 +58,8 @@ var generateNonce = () => { | ||
} | ||
if (options.permissionsPolicy && Object.keys(options.permissionsPolicy).length > 0) { | ||
headersToSet.push([ | ||
"Permissions-Policy", | ||
getPermissionsPolicyDirectives(options.permissionsPolicy) | ||
]); | ||
} | ||
if (options.reportingEndpoints) { | ||
@@ -117,2 +124,24 @@ headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]); | ||
} | ||
function getPermissionsPolicyDirectives(policy) { | ||
return Object.entries(policy).map(([directive, value]) => { | ||
const kebabDirective = camelToKebab(directive); | ||
if (typeof value === "boolean") { | ||
return `${kebabDirective}=${value ? "*" : "none"}`; | ||
} | ||
if (Array.isArray(value)) { | ||
if (value.length === 0) { | ||
return `${kebabDirective}=()`; | ||
} | ||
if (value.length === 1 && (value[0] === "*" || value[0] === "none")) { | ||
return `${kebabDirective}=${value[0]}`; | ||
} | ||
const allowlist = value.map((item) => ["self", "src"].includes(item) ? item : `"${item}"`); | ||
return `${kebabDirective}=(${allowlist.join(" ")})`; | ||
} | ||
return ""; | ||
}).filter(Boolean).join(", "); | ||
} | ||
function camelToKebab(str) { | ||
return str.replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase(); | ||
} | ||
function getReportingEndpoints(reportingEndpoints = []) { | ||
@@ -119,0 +148,0 @@ return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", "); |
// src/middleware/serve-static/index.ts | ||
import { getFilePath, getFilePathWithoutDefaultDocument } from "../../utils/filepath.js"; | ||
import { getMimeType } from "../../utils/mime.js"; | ||
var ENCODINGS = { | ||
br: ".br", | ||
zstd: ".zst", | ||
gzip: ".gz" | ||
}; | ||
var DEFAULT_DOCUMENT = "index.html"; | ||
@@ -21,3 +26,3 @@ var defaultPathResolve = (path) => path; | ||
if (path2 && await options.isDir(path2)) { | ||
filename = filename + "/"; | ||
filename += "/"; | ||
} | ||
@@ -38,14 +43,14 @@ } | ||
if (!content) { | ||
let pathWithOutDefaultDocument = getFilePathWithoutDefaultDocument({ | ||
let pathWithoutDefaultDocument = getFilePathWithoutDefaultDocument({ | ||
filename, | ||
root | ||
}); | ||
if (!pathWithOutDefaultDocument) { | ||
if (!pathWithoutDefaultDocument) { | ||
return await next(); | ||
} | ||
pathWithOutDefaultDocument = pathResolve(pathWithOutDefaultDocument); | ||
if (pathWithOutDefaultDocument !== path) { | ||
content = await getContent(pathWithOutDefaultDocument, c); | ||
pathWithoutDefaultDocument = pathResolve(pathWithoutDefaultDocument); | ||
if (pathWithoutDefaultDocument !== path) { | ||
content = await getContent(pathWithoutDefaultDocument, c); | ||
if (content) { | ||
path = pathWithOutDefaultDocument; | ||
path = pathWithoutDefaultDocument; | ||
} | ||
@@ -57,12 +62,24 @@ } | ||
} | ||
const mimeType = options.mimes ? getMimeType(path, options.mimes) ?? getMimeType(path) : getMimeType(path); | ||
if (mimeType) { | ||
c.header("Content-Type", mimeType); | ||
} | ||
if (content) { | ||
let mimeType; | ||
if (options.mimes) { | ||
mimeType = getMimeType(path, options.mimes) ?? getMimeType(path); | ||
} else { | ||
mimeType = getMimeType(path); | ||
if (options.precompressed) { | ||
const acceptEncodings = c.req.header("Accept-Encoding")?.split(",").map((encoding) => encoding.trim()).filter( | ||
(encoding) => Object.hasOwn(ENCODINGS, encoding) | ||
).sort( | ||
(a, b) => Object.keys(ENCODINGS).indexOf(a) - Object.keys(ENCODINGS).indexOf(b) | ||
) ?? []; | ||
for (const encoding of acceptEncodings) { | ||
const compressedContent = await getContent(path + ENCODINGS[encoding], c); | ||
if (compressedContent) { | ||
content = compressedContent; | ||
c.header("Content-Encoding", encoding); | ||
c.header("Vary", "Accept-Encoding", { append: true }); | ||
break; | ||
} | ||
} | ||
} | ||
if (mimeType) { | ||
c.header("Content-Type", mimeType); | ||
} | ||
await options.onFound?.(path, c); | ||
return c.body(content); | ||
@@ -69,0 +86,0 @@ } |
@@ -13,7 +13,5 @@ import type { UpgradeWebSocket } from '../../helper/websocket'; | ||
} | ||
interface CreateWebSocket { | ||
(): { | ||
upgradeWebSocket: UpgradeWebSocket; | ||
websocket: BunWebSocketHandler<BunWebSocketData>; | ||
}; | ||
interface CreateWebSocket<T> { | ||
upgradeWebSocket: UpgradeWebSocket<T>; | ||
websocket: BunWebSocketHandler<BunWebSocketData>; | ||
} | ||
@@ -25,3 +23,3 @@ export interface BunWebSocketData { | ||
} | ||
export declare const createBunWebSocket: CreateWebSocket; | ||
export declare const createBunWebSocket: <T>() => CreateWebSocket<T>; | ||
export {}; |
import type { Hono } from '../../hono'; | ||
import type { BlankSchema, Env, Input, MiddlewareHandler, Schema } from '../../types'; | ||
type Params<P extends string = any> = Record<P, string | string[]>; | ||
export type EventContext<Env = {}, P extends string = any, Data = {}> = { | ||
export type EventContext<Env = {}, P extends string = any, Data = Record<string, unknown>> = { | ||
request: Request; | ||
@@ -20,3 +20,7 @@ functionPath: string; | ||
export declare const handle: <E extends Env = Env, S extends Schema = BlankSchema, BasePath extends string = "/">(app: Hono<E, S, BasePath>) => PagesFunction<E["Bindings"], any, Record<string, unknown>>; | ||
export declare function handleMiddleware<E extends Env = any, P extends string = any, I extends Input = {}>(middleware: MiddlewareHandler<E, P, I>): PagesFunction<E['Bindings']>; | ||
export declare function handleMiddleware<E extends Env = {}, P extends string = any, I extends Input = {}>(middleware: MiddlewareHandler<E & { | ||
Bindings: { | ||
eventContext: EventContext; | ||
}; | ||
}, P, I>): PagesFunction<E['Bindings']>; | ||
/** | ||
@@ -23,0 +27,0 @@ * |
import type { UpgradeWebSocket } from '../../helper/websocket'; | ||
export declare const upgradeWebSocket: UpgradeWebSocket; | ||
export declare const upgradeWebSocket: UpgradeWebSocket<WebSocket>; |
@@ -21,2 +21,2 @@ import type { UpgradeWebSocket } from '../../helper/websocket'; | ||
} | ||
export declare const upgradeWebSocket: UpgradeWebSocket<UpgradeWebSocketOptions>; | ||
export declare const upgradeWebSocket: UpgradeWebSocket<WebSocket, UpgradeWebSocketOptions>; |
import type { Context } from '../../context'; | ||
import { StreamingApi } from '../../utils/stream'; | ||
export interface SSEMessage { | ||
data: string; | ||
data: string | Promise<string>; | ||
event?: string; | ||
@@ -6,0 +6,0 @@ id?: string; |
@@ -10,7 +10,7 @@ /** | ||
*/ | ||
export interface WSEvents { | ||
onOpen?: (evt: Event, ws: WSContext) => void; | ||
onMessage?: (evt: MessageEvent<WSMessageReceive>, ws: WSContext) => void; | ||
onClose?: (evt: CloseEvent, ws: WSContext) => void; | ||
onError?: (evt: Event, ws: WSContext) => void; | ||
export interface WSEvents<T = unknown> { | ||
onOpen?: (evt: Event, ws: WSContext<T>) => void; | ||
onMessage?: (evt: MessageEvent<WSMessageReceive>, ws: WSContext<T>) => void; | ||
onClose?: (evt: CloseEvent, ws: WSContext<T>) => void; | ||
onError?: (evt: Event, ws: WSContext<T>) => void; | ||
} | ||
@@ -20,11 +20,11 @@ /** | ||
*/ | ||
export type UpgradeWebSocket<T = any> = (createEvents: (c: Context) => WSEvents | Promise<WSEvents>, options?: T) => MiddlewareHandler<any, string, { | ||
export type UpgradeWebSocket<T = unknown, U = any> = (createEvents: (c: Context) => WSEvents<T> | Promise<WSEvents<T>>, options?: U) => MiddlewareHandler<any, string, { | ||
outputFormat: 'ws'; | ||
}>; | ||
export type WSReadyState = 0 | 1 | 2 | 3; | ||
export type WSContext = { | ||
export type WSContext<T = unknown> = { | ||
send(source: string | ArrayBuffer | Uint8Array, options?: { | ||
compress: boolean; | ||
}): void; | ||
raw?: unknown; | ||
raw?: T; | ||
binaryType: BinaryType; | ||
@@ -31,0 +31,0 @@ readyState: WSReadyState; |
@@ -7,2 +7,3 @@ /** | ||
import type { MiddlewareHandler } from '../../types'; | ||
type MessageFunction = (c: Context) => string | object | Promise<string | object>; | ||
type BasicAuthOptions = { | ||
@@ -13,2 +14,3 @@ username: string; | ||
hashFunction?: Function; | ||
invalidUserMessage?: string | object | MessageFunction; | ||
} | { | ||
@@ -18,2 +20,3 @@ verifyUser: (username: string, password: string, c: Context) => boolean | Promise<boolean>; | ||
hashFunction?: Function; | ||
invalidUserMessage?: string | object | MessageFunction; | ||
}; | ||
@@ -31,2 +34,3 @@ /** | ||
* @param {Function} [options.verifyUser] - The function to verify user credentials. | ||
* @param {string | object | MessageFunction} [options.invalidUserMessage="Unauthorized"] - The invalid user message. | ||
* @returns {MiddlewareHandler} The middleware handler function. | ||
@@ -33,0 +37,0 @@ * @throws {HTTPException} If neither "username and password" nor "verifyUser" options are provided. |
@@ -7,2 +7,3 @@ /** | ||
import type { MiddlewareHandler } from '../../types'; | ||
type MessageFunction = (c: Context) => string | object | Promise<string | object>; | ||
type BearerAuthOptions = { | ||
@@ -14,2 +15,5 @@ token: string | string[]; | ||
hashFunction?: Function; | ||
noAuthenticationHeaderMessage?: string | object | MessageFunction; | ||
invalidAuthenticationHeaderMessage?: string | object | MessageFunction; | ||
invalidTokenMessage?: string | object | MessageFunction; | ||
} | { | ||
@@ -21,2 +25,5 @@ realm?: string; | ||
hashFunction?: Function; | ||
noAuthenticationHeaderMessage?: string | object | MessageFunction; | ||
invalidAuthenticationHeaderMessage?: string | object | MessageFunction; | ||
invalidTokenMessage?: string | object | MessageFunction; | ||
}; | ||
@@ -35,2 +42,5 @@ /** | ||
* @param {Function} [options.hashFunction] - A function to handle hashing for safe comparison of authentication tokens. | ||
* @param {string | object | MessageFunction} [options.noAuthenticationHeaderMessage="Unauthorized"] - The no authentication header message. | ||
* @param {string | object | MessageFunction} [options.invalidAuthenticationHeaderMeasage="Bad Request"] - The invalid authentication header message. | ||
* @param {string | object | MessageFunction} [options.invalidTokenMessage="Unauthorized"] - The invalid token message. | ||
* @returns {MiddlewareHandler} The middleware handler function. | ||
@@ -37,0 +47,0 @@ * @throws {Error} If neither "token" nor "verifyToken" options are provided. |
/** | ||
* @module | ||
* JSR Renderer Middleware for Hono. | ||
* JSX Renderer Middleware for Hono. | ||
*/ | ||
@@ -5,0 +5,0 @@ import type { Context, PropsForRenderer } from '../../context'; |
@@ -7,2 +7,3 @@ /** | ||
import type { MiddlewareHandler } from '../../types'; | ||
import type { PermissionsPolicyDirective } from './permissions-policy'; | ||
export type SecureHeadersVariables = { | ||
@@ -49,2 +50,4 @@ secureHeadersNonce?: string; | ||
} | ||
type PermissionsPolicyValue = '*' | 'self' | 'src' | 'none' | string; | ||
type PermissionsPolicyOptions = Partial<Record<PermissionsPolicyDirective, PermissionsPolicyValue[] | boolean>>; | ||
type overridableHeader = boolean | string; | ||
@@ -68,2 +71,3 @@ interface SecureHeadersOptions { | ||
removePoweredBy?: boolean; | ||
permissionsPolicy?: PermissionsPolicyOptions; | ||
} | ||
@@ -93,2 +97,3 @@ export declare const NONCE: ContentSecurityPolicyOptionHandler; | ||
* @param {boolean} [customOptions.removePoweredBy=true] - Settings for remove X-Powered-By header. | ||
* @param {PermissionsPolicyOptions} [customOptions.permissionsPolicy] - Settings for the Permissions-Policy header. | ||
* @returns {MiddlewareHandler} The middleware handler function. | ||
@@ -95,0 +100,0 @@ * |
@@ -10,4 +10,6 @@ /** | ||
path?: string; | ||
precompressed?: boolean; | ||
mimes?: Record<string, string>; | ||
rewriteRequestPath?: (path: string) => string; | ||
onFound?: (path: string, c: Context<E>) => void | Promise<void>; | ||
onNotFound?: (path: string, c: Context<E>) => void | Promise<void>; | ||
@@ -14,0 +16,0 @@ }; |
@@ -43,3 +43,3 @@ /** | ||
export declare const resolveCallbackSync: (str: string | HtmlEscapedString) => string; | ||
export declare const resolveCallback: (str: string | HtmlEscapedString, phase: (typeof HtmlEscapedCallbackPhase)[keyof typeof HtmlEscapedCallbackPhase], preserveCallbacks: boolean, context: object, buffer?: [string]) => Promise<string>; | ||
export declare const resolveCallback: (str: string | HtmlEscapedString | Promise<string>, phase: (typeof HtmlEscapedCallbackPhase)[keyof typeof HtmlEscapedCallbackPhase], preserveCallbacks: boolean, context: object, buffer?: [string]) => Promise<string>; | ||
export {}; |
@@ -88,2 +88,10 @@ // src/utils/html.ts | ||
var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => { | ||
if (typeof str === "object" && !(str instanceof String)) { | ||
if (!(str instanceof Promise)) { | ||
str = str.toString(); | ||
} | ||
if (str instanceof Promise) { | ||
str = await str; | ||
} | ||
} | ||
const callbacks = str.callbacks; | ||
@@ -90,0 +98,0 @@ if (!callbacks?.length) { |
{ | ||
"name": "hono", | ||
"version": "4.5.11", | ||
"version": "4.6.0", | ||
"description": "Web framework built on Web Standards", | ||
@@ -107,2 +107,7 @@ "main": "dist/cjs/index.js", | ||
}, | ||
"./context-storage": { | ||
"types": "./dist/types/middleware/context-storage/index.d.ts", | ||
"import": "./dist/middleware/context-storage/index.js", | ||
"require": "./dist/cjs/middleware/context-storage/index.js" | ||
}, | ||
"./cors": { | ||
@@ -425,2 +430,5 @@ "types": "./dist/types/middleware/cors/index.d.ts", | ||
], | ||
"context-storage": [ | ||
"./dist/types/middleware/context-storage" | ||
], | ||
"cors": [ | ||
@@ -427,0 +435,0 @@ "./dist/types/middleware/cors" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1032980
496
29150