mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 22:37:29 +00:00
Handle bad feed path encoding (#9)
This commit is contained in:
parent
3d4345b665
commit
8f4691584c
2 changed files with 28 additions and 4 deletions
|
|
@ -118,6 +118,14 @@ describe("CommandBoard API contracts", () => {
|
||||||
expect(opmlBody).toContain("<opml");
|
expect(opmlBody).toContain("<opml");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("rejects malformed encoded feed discovery paths as client errors", async () => {
|
||||||
|
const response = await fetch(`${baseUrl}/rss/discover/%E0%A4%A.xml`);
|
||||||
|
const body = await response.json() as { error: string };
|
||||||
|
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
expect(body).toEqual({ error: "Invalid path encoding" });
|
||||||
|
});
|
||||||
|
|
||||||
it("exposes sh1pt project and action contracts", async () => {
|
it("exposes sh1pt project and action contracts", async () => {
|
||||||
const projectsResponse = await fetch(`${baseUrl}/api/plugins/sh1pt/projects`);
|
const projectsResponse = await fetch(`${baseUrl}/api/plugins/sh1pt/projects`);
|
||||||
const projectsBody = await projectsResponse.json() as { projects: Array<{ id: string; board: string; status: string; actions: number }> };
|
const projectsBody = await projectsResponse.json() as { projects: Array<{ id: string; board: string; status: string; actions: number }> };
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,11 @@ async function route(request: IncomingMessage, response: ServerResponse) {
|
||||||
|
|
||||||
const formattedDiscover = matchFormattedDiscoverPath(url.pathname);
|
const formattedDiscover = matchFormattedDiscoverPath(url.pathname);
|
||||||
if (request.method === "GET" && formattedDiscover) {
|
if (request.method === "GET" && formattedDiscover) {
|
||||||
|
if (formattedDiscover.format === "invalid-encoding") {
|
||||||
|
json(response, 400, { error: "Invalid path encoding" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const result = await discoverFeeds({
|
const result = await discoverFeeds({
|
||||||
q: formattedDiscover.keyword,
|
q: formattedDiscover.keyword,
|
||||||
type: "all",
|
type: "all",
|
||||||
|
|
@ -344,23 +349,34 @@ function listParam(value: string | null) {
|
||||||
function matchFormattedDiscoverPath(pathname: string) {
|
function matchFormattedDiscoverPath(pathname: string) {
|
||||||
const rss = /^\/rss\/discover\/(.+)\.xml$/.exec(pathname);
|
const rss = /^\/rss\/discover\/(.+)\.xml$/.exec(pathname);
|
||||||
if (rss) {
|
if (rss) {
|
||||||
return { format: "rss" as const, keyword: decodeURIComponent(rss[1]) };
|
return formattedDiscoverMatch("rss", rss[1]);
|
||||||
}
|
}
|
||||||
const opml = /^\/opml\/discover\/(.+)\.xml$/.exec(pathname) ?? /^\/rss\/discover\/(.+)\.opml$/.exec(pathname);
|
const opml = /^\/opml\/discover\/(.+)\.xml$/.exec(pathname) ?? /^\/rss\/discover\/(.+)\.opml$/.exec(pathname);
|
||||||
if (opml) {
|
if (opml) {
|
||||||
return { format: "opml" as const, keyword: decodeURIComponent(opml[1]) };
|
return formattedDiscoverMatch("opml", opml[1]);
|
||||||
}
|
}
|
||||||
const atom = /^\/atom\/discover\/(.+)\.xml$/.exec(pathname);
|
const atom = /^\/atom\/discover\/(.+)\.xml$/.exec(pathname);
|
||||||
if (atom) {
|
if (atom) {
|
||||||
return { format: "atom" as const, keyword: decodeURIComponent(atom[1]) };
|
return formattedDiscoverMatch("atom", atom[1]);
|
||||||
}
|
}
|
||||||
const jsonFeed = /^\/json-feed\/discover\/(.+)\.json$/.exec(pathname);
|
const jsonFeed = /^\/json-feed\/discover\/(.+)\.json$/.exec(pathname);
|
||||||
if (jsonFeed) {
|
if (jsonFeed) {
|
||||||
return { format: "json-feed" as const, keyword: decodeURIComponent(jsonFeed[1]) };
|
return formattedDiscoverMatch("json-feed", jsonFeed[1]);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formattedDiscoverMatch(format: "rss" | "opml" | "atom" | "json-feed", encodedKeyword: string) {
|
||||||
|
try {
|
||||||
|
return { format, keyword: decodeURIComponent(encodedKeyword) };
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof URIError) {
|
||||||
|
return { format: "invalid-encoding" as const };
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function startCommandBoardServer(port = Number(process.env.PORT ?? 4010)) {
|
export function startCommandBoardServer(port = Number(process.env.PORT ?? 4010)) {
|
||||||
const server = createCommandBoardServer();
|
const server = createCommandBoardServer();
|
||||||
server.listen(port, () => {
|
server.listen(port, () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue