Refactor/fix error handling, add query timeouts
This commit is contained in:
parent
ec7c775e25
commit
5f5f024ae7
@ -45,6 +45,7 @@ const config = {
|
|||||||
password: Deno.env.get("LDAP_PASSWORD"),
|
password: Deno.env.get("LDAP_PASSWORD"),
|
||||||
searchDN: Deno.env.get("LDAP_SEARCH_DN"),
|
searchDN: Deno.env.get("LDAP_SEARCH_DN"),
|
||||||
},
|
},
|
||||||
|
query_timeout: parseInt(Deno.env.get("RELAY_TIMEOUT_MS") || "5000"),
|
||||||
njump_url: Deno.env.get("NJUMP_URL") || "https://njump.me",
|
njump_url: Deno.env.get("NJUMP_URL") || "https://njump.me",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
20
handlers/errors.ts
Normal file
20
handlers/errors.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Context } from "@oak/oak";
|
||||||
|
import { errorPageHtml } from "../html.ts";
|
||||||
|
|
||||||
|
export const notFoundHandler = function (ctx: Context) {
|
||||||
|
const html = errorPageHtml(404, "Not found");
|
||||||
|
ctx.response.body = html;
|
||||||
|
ctx.response.status = 404;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const badGatewayHandler = function (ctx: Context) {
|
||||||
|
const html = errorPageHtml(502, "Bad gateway");
|
||||||
|
ctx.response.body = html;
|
||||||
|
ctx.response.status = 502;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const internalServerErrorHandler = function (ctx: Context) {
|
||||||
|
const html = errorPageHtml(500, "Internal server error");
|
||||||
|
ctx.response.body = html;
|
||||||
|
ctx.response.status = 500;
|
||||||
|
};
|
@ -1,22 +1,25 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
|
|
||||||
const naddrHandler = async function (ctx: Context) {
|
const naddrHandler = async function (ctx: Context) {
|
||||||
const naddr = ctx.state.path;
|
const naddr = ctx.state.path;
|
||||||
|
let data: nip19.AddressPointer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = nip19.decode(naddr).data as nip19.AddressPointer;
|
data = nip19.decode(naddr).data as nip19.AddressPointer;
|
||||||
const username = await lookupUsernameByPubkey(data.pubkey);
|
|
||||||
|
|
||||||
if (username && data.identifier) {
|
|
||||||
ctx.response.redirect(`/@${username}/${data.identifier}`);
|
|
||||||
} else {
|
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = await lookupUsernameByPubkey(data.pubkey);
|
||||||
|
|
||||||
|
if (username && data.identifier) {
|
||||||
|
ctx.response.redirect(`/@${username}/${data.identifier}`);
|
||||||
|
} else {
|
||||||
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { Context } from "@oak/oak";
|
|
||||||
import { errorPageHtml } from "../html.ts";
|
|
||||||
|
|
||||||
const notFoundHandler = function (ctx: Context) {
|
|
||||||
const html = errorPageHtml(404, "Not found");
|
|
||||||
ctx.response.body = html;
|
|
||||||
ctx.response.status = 404;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default notFoundHandler;
|
|
@ -1,22 +1,26 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
|
|
||||||
const nprofileHandler = async function (ctx: Context) {
|
const nprofileHandler = async function (ctx: Context) {
|
||||||
const nprofile = ctx.state.path;
|
const nprofile = ctx.state.path;
|
||||||
|
let data: nip19.ProfilePointer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = nip19.decode(nprofile).data as nip19.ProfilePointer;
|
data = nip19.decode(nprofile).data as nip19.ProfilePointer;
|
||||||
const username = await lookupUsernameByPubkey(data.pubkey);
|
console.log(data);
|
||||||
|
|
||||||
if (username) {
|
|
||||||
ctx.response.redirect(`/@${username}`);
|
|
||||||
} else {
|
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = await lookupUsernameByPubkey(data.pubkey);
|
||||||
|
|
||||||
|
if (username) {
|
||||||
|
ctx.response.redirect(`/@${username}`);
|
||||||
|
} else {
|
||||||
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
import { Context } from "@oak/oak";
|
import { Context } from "@oak/oak";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { lookupUsernameByPubkey } from "../directory.ts";
|
import { lookupUsernameByPubkey } from "../directory.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
|
|
||||||
const npubHandler = async function (ctx: Context) {
|
const npubHandler = async function (ctx: Context) {
|
||||||
const npub = ctx.state.path;
|
const npub = ctx.state.path;
|
||||||
|
let pubkey: string;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pubkey = nip19.decode(npub).data as string;
|
pubkey = nip19.decode(npub).data as string;
|
||||||
const username = await lookupUsernameByPubkey(pubkey);
|
|
||||||
|
|
||||||
if (username) {
|
|
||||||
ctx.response.redirect(`/@${username}`);
|
|
||||||
} else {
|
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = await lookupUsernameByPubkey(pubkey);
|
||||||
|
|
||||||
|
if (username) {
|
||||||
|
ctx.response.redirect(`/@${username}`);
|
||||||
|
} else {
|
||||||
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
|||||||
import { profileAtomFeed } from "../feeds.ts";
|
import { profileAtomFeed } from "../feeds.ts";
|
||||||
import Article from "../models/article.ts";
|
import Article from "../models/article.ts";
|
||||||
import Profile from "../models/profile.ts";
|
import Profile from "../models/profile.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
|
|
||||||
const userAtomFeedHandler = async function (ctx: Context) {
|
const userAtomFeedHandler = async function (ctx: Context) {
|
||||||
const username = ctx.state.username;
|
const username = ctx.state.username;
|
||||||
@ -15,26 +15,22 @@ const userAtomFeedHandler = async function (ctx: Context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const profileEvent = await fetchProfileEvent(pubkey);
|
||||||
const profileEvent = await fetchProfileEvent(pubkey);
|
|
||||||
|
|
||||||
if (profileEvent) {
|
if (profileEvent) {
|
||||||
const profile = new Profile(profileEvent, username);
|
const profile = new Profile(profileEvent, username);
|
||||||
|
|
||||||
if (profile.nip05) {
|
if (profile.nip05) {
|
||||||
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
||||||
const articles = articleEvents.map((a) => new Article(a));
|
const articles = articleEvents.map((a) => new Article(a));
|
||||||
const atom = profileAtomFeed(profile, articles);
|
const atom = profileAtomFeed(profile, articles);
|
||||||
|
|
||||||
ctx.response.headers.set("Content-Type", "application/atom+xml");
|
ctx.response.headers.set("Content-Type", "application/atom+xml");
|
||||||
ctx.response.body = atom;
|
ctx.response.body = atom;
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
notFoundHandler(ctx);
|
|
||||||
} catch (_e) {
|
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
}
|
||||||
|
notFoundHandler(ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default userAtomFeedHandler;
|
export default userAtomFeedHandler;
|
||||||
|
@ -4,7 +4,7 @@ import { fetchProfileEvent, fetchReplaceableEvent } from "../nostr.ts";
|
|||||||
import Article from "../models/article.ts";
|
import Article from "../models/article.ts";
|
||||||
import Profile from "../models/profile.ts";
|
import Profile from "../models/profile.ts";
|
||||||
import { articleHtml } from "../html.ts";
|
import { articleHtml } from "../html.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
import { generateOgProfileImage } from "../magick.ts";
|
import { generateOgProfileImage } from "../magick.ts";
|
||||||
|
|
||||||
const userEventHandler = async function (ctx: Context) {
|
const userEventHandler = async function (ctx: Context) {
|
||||||
@ -17,24 +17,20 @@ const userEventHandler = async function (ctx: Context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const articleEvent = await fetchReplaceableEvent(
|
||||||
const articleEvent = await fetchReplaceableEvent(
|
pubkey,
|
||||||
pubkey,
|
identifier,
|
||||||
identifier,
|
);
|
||||||
);
|
const profileEvent = await fetchProfileEvent(pubkey);
|
||||||
const profileEvent = await fetchProfileEvent(pubkey);
|
|
||||||
|
|
||||||
if (articleEvent && profileEvent) {
|
if (articleEvent && profileEvent) {
|
||||||
const article = new Article(articleEvent);
|
const article = new Article(articleEvent);
|
||||||
const profile = new Profile(profileEvent, username);
|
const profile = new Profile(profileEvent, username);
|
||||||
const html = await articleHtml(article, profile);
|
const html = await articleHtml(article, profile);
|
||||||
generateOgProfileImage(profile);
|
generateOgProfileImage(profile);
|
||||||
|
|
||||||
ctx.response.body = html;
|
ctx.response.body = html;
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
|||||||
import Article from "../models/article.ts";
|
import Article from "../models/article.ts";
|
||||||
import Profile from "../models/profile.ts";
|
import Profile from "../models/profile.ts";
|
||||||
import { profilePageHtml } from "../html.ts";
|
import { profilePageHtml } from "../html.ts";
|
||||||
import notFoundHandler from "../handlers/not-found.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
import { generateOgProfileImage } from "../magick.ts";
|
import { generateOgProfileImage } from "../magick.ts";
|
||||||
|
|
||||||
const userProfileHandler = async function (ctx: Context) {
|
const userProfileHandler = async function (ctx: Context) {
|
||||||
@ -16,21 +16,17 @@ const userProfileHandler = async function (ctx: Context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const profileEvent = await fetchProfileEvent(pubkey);
|
||||||
const profileEvent = await fetchProfileEvent(pubkey);
|
|
||||||
|
|
||||||
if (profileEvent) {
|
if (profileEvent) {
|
||||||
const profile = new Profile(profileEvent, username);
|
const profile = new Profile(profileEvent, username);
|
||||||
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
const articleEvents = await fetchArticlesByAuthor(pubkey);
|
||||||
const articles = articleEvents.map((a) => new Article(a));
|
const articles = articleEvents.map((a) => new Article(a));
|
||||||
const html = profilePageHtml(profile, articles);
|
const html = profilePageHtml(profile, articles);
|
||||||
generateOgProfileImage(profile);
|
generateOgProfileImage(profile);
|
||||||
|
|
||||||
ctx.response.body = html;
|
ctx.response.body = html;
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
10
ldap.ts
10
ldap.ts
@ -25,10 +25,11 @@ export async function lookupPubkeyByUsername(username: string) {
|
|||||||
) {
|
) {
|
||||||
pubkey = searchEntries[0].nostrKey;
|
pubkey = searchEntries[0].nostrKey;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
await client.unbind();
|
await client.unbind();
|
||||||
|
} catch (e) {
|
||||||
|
await client.unbind();
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pubkey;
|
return pubkey;
|
||||||
@ -49,9 +50,8 @@ export async function lookupUsernameByPubkey(pubkey: string) {
|
|||||||
username = searchEntries[0].cn;
|
username = searchEntries[0].cn;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
await client.unbind();
|
await client.unbind();
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return username;
|
return username;
|
||||||
|
28
nostr.ts
28
nostr.ts
@ -1,4 +1,4 @@
|
|||||||
import { NPool, NRelay1 } from "@nostrify/nostrify";
|
import { NostrEvent, NostrFilter, NPool, NRelay1 } from "@nostrify/nostrify";
|
||||||
import { nip19 } from "@nostr/tools";
|
import { nip19 } from "@nostr/tools";
|
||||||
import { lookupUsernameByPubkey } from "./directory.ts";
|
import { lookupUsernameByPubkey } from "./directory.ts";
|
||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
@ -14,47 +14,57 @@ const relayPool = new NPool({
|
|||||||
eventRouter: async (_event) => [],
|
eventRouter: async (_event) => [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function fetchWithTimeout(filters: NostrFilter[]) {
|
||||||
|
const timeoutPromise = new Promise((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error("relay timeout")), config.query_timeout)
|
||||||
|
);
|
||||||
|
const eventsPromise = relayPool.query(filters);
|
||||||
|
|
||||||
|
const events = await Promise.race([eventsPromise, timeoutPromise]);
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchReplaceableEvent(
|
export async function fetchReplaceableEvent(
|
||||||
pubkey: string,
|
pubkey: string,
|
||||||
identifier: string,
|
identifier: string,
|
||||||
) {
|
) {
|
||||||
let events = await relayPool.query([{
|
let events = await fetchWithTimeout([{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [30023],
|
kinds: [30023],
|
||||||
"#d": [identifier],
|
"#d": [identifier],
|
||||||
limit: 1,
|
limit: 1,
|
||||||
}]);
|
}]) as NostrEvent[];
|
||||||
|
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
return events[0];
|
return events[0];
|
||||||
} else {
|
} else {
|
||||||
events = await relayPool.query([{
|
events = await fetchWithTimeout([{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [30024],
|
kinds: [30024],
|
||||||
"#d": [identifier],
|
"#d": [identifier],
|
||||||
limit: 1,
|
limit: 1,
|
||||||
}]);
|
}]) as NostrEvent[];
|
||||||
|
|
||||||
return events.length > 0 ? events[0] : null;
|
return events.length > 0 ? events[0] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchArticlesByAuthor(pubkey: string) {
|
export async function fetchArticlesByAuthor(pubkey: string) {
|
||||||
const events = await relayPool.query([{
|
const events = await fetchWithTimeout([{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [30023],
|
kinds: [30023],
|
||||||
limit: 10,
|
limit: 10,
|
||||||
}]);
|
}]) as NostrEvent[];
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchProfileEvent(pubkey: string) {
|
export async function fetchProfileEvent(pubkey: string) {
|
||||||
const events = await relayPool.query([{
|
const events = await fetchWithTimeout([{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [0],
|
kinds: [0],
|
||||||
limit: 1,
|
limit: 1,
|
||||||
}]);
|
}]) as NostrEvent[];
|
||||||
|
|
||||||
return events.length > 0 ? events[0] : null;
|
return events.length > 0 ? events[0] : null;
|
||||||
}
|
}
|
||||||
|
66
server.ts
66
server.ts
@ -7,23 +7,36 @@ import npubHandler from "./handlers/npub.ts";
|
|||||||
import userProfileHandler from "./handlers/user-profile.ts";
|
import userProfileHandler from "./handlers/user-profile.ts";
|
||||||
import userEventHandler from "./handlers/user-event.ts";
|
import userEventHandler from "./handlers/user-event.ts";
|
||||||
import userAtomFeedHandler from "./handlers/user-atom-feed.ts";
|
import userAtomFeedHandler from "./handlers/user-atom-feed.ts";
|
||||||
import notFoundHandler from "./handlers/not-found.ts";
|
import {
|
||||||
|
badGatewayHandler,
|
||||||
|
internalServerErrorHandler,
|
||||||
|
notFoundHandler,
|
||||||
|
} from "./handlers/errors.ts";
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.get("/:path", async (ctx) => {
|
router.get("/:path", async (ctx) => {
|
||||||
const path = ctx.state.path = ctx.params.path;
|
const path = ctx.state.path = ctx.params.path;
|
||||||
|
|
||||||
if (path.startsWith("naddr")) {
|
try {
|
||||||
await naddrHandler(ctx);
|
if (path.startsWith("naddr")) {
|
||||||
} else if (path.startsWith("nprofile")) {
|
await naddrHandler(ctx);
|
||||||
await nprofileHandler(ctx);
|
} else if (path.startsWith("nprofile")) {
|
||||||
} else if (path.startsWith("npub")) {
|
await nprofileHandler(ctx);
|
||||||
await npubHandler(ctx);
|
} else if (path.startsWith("npub")) {
|
||||||
} else if (path.startsWith("@") || path.startsWith("~")) {
|
await npubHandler(ctx);
|
||||||
await userProfileHandler(ctx);
|
} else if (path.startsWith("@") || path.startsWith("~")) {
|
||||||
} else {
|
await userProfileHandler(ctx);
|
||||||
notFoundHandler(ctx);
|
} else {
|
||||||
|
notFoundHandler(ctx);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
if (e instanceof Error && e.message.match(/^connect|relay timeout/)) {
|
||||||
|
badGatewayHandler(ctx);
|
||||||
|
} else {
|
||||||
|
internalServerErrorHandler(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -36,7 +49,16 @@ router.get("/:username/:kind.atom", async (ctx) => {
|
|||||||
(ctx.params.username.startsWith("@") ||
|
(ctx.params.username.startsWith("@") ||
|
||||||
ctx.params.username.startsWith("~"))
|
ctx.params.username.startsWith("~"))
|
||||||
) {
|
) {
|
||||||
await userAtomFeedHandler(ctx);
|
try {
|
||||||
|
await userAtomFeedHandler(ctx);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
if (e instanceof Error && e.message.match(/^connect|relay timeout/)) {
|
||||||
|
badGatewayHandler(ctx);
|
||||||
|
} else {
|
||||||
|
internalServerErrorHandler(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
@ -47,7 +69,16 @@ router.get("/:username/:identifier", async (ctx) => {
|
|||||||
ctx.state.identifier = ctx.params.identifier;
|
ctx.state.identifier = ctx.params.identifier;
|
||||||
|
|
||||||
if (username.startsWith("@") || username.startsWith("~")) {
|
if (username.startsWith("@") || username.startsWith("~")) {
|
||||||
await userEventHandler(ctx);
|
try {
|
||||||
|
await userEventHandler(ctx);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
if (e instanceof Error && e.message.match(/^connect|relay timeout/)) {
|
||||||
|
badGatewayHandler(ctx);
|
||||||
|
} else {
|
||||||
|
internalServerErrorHandler(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
notFoundHandler(ctx);
|
notFoundHandler(ctx);
|
||||||
}
|
}
|
||||||
@ -66,8 +97,13 @@ router.get("/assets/:path*", async (ctx) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await send(ctx, filePath, { root });
|
await send(ctx, filePath, { root });
|
||||||
} catch (_e) {
|
} catch (e) {
|
||||||
notFoundHandler(ctx);
|
if (e instanceof Error && e.name === "NotFoundError") {
|
||||||
|
notFoundHandler(ctx);
|
||||||
|
} else {
|
||||||
|
console.error(e);
|
||||||
|
badGatewayHandler(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user