mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
fix(feeds): self link uses configured domain, not request host
The RSS/Atom/JSON self link was derived from the request origin, leaking the workers.dev host when reached directly instead of via the custom domain. Use the configured-domain URL builders so self matches alternate. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -117,10 +117,12 @@ describe("Atom Feed Route", () => {
|
|||||||
expect(body).toContain("Atom Test Feed");
|
expect(body).toContain("Atom Test Feed");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("self-link points to atom URL", async () => {
|
it("self-link uses the configured domain, not the request host", async () => {
|
||||||
const res = await testApp.request(`/${FEED_ID}`, {}, mockEnv);
|
const res = await testApp.request(`/${FEED_ID}`, {}, mockEnv);
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
expect(body).toContain(`/atom/${FEED_ID}`);
|
expect(body).toContain(
|
||||||
|
`rel="self" href="https://${mockEnv.DOMAIN}/atom/${FEED_ID}"`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Link header advertises hub and self for WebSub discovery", async () => {
|
it("Link header advertises hub and self for WebSub discovery", async () => {
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ export async function handle(c: Context<{ Bindings: Env }>): Promise<Response> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base = baseUrl(c.env);
|
const base = baseUrl(c.env);
|
||||||
const selfUrl = new URL(c.req.url).origin + `/atom/${feedId}`;
|
const selfUrl = feedAtomUrl(feedId, c.env);
|
||||||
const atomXml = generateAtomFeed(
|
const atomXml = generateAtomFeed(
|
||||||
feedData.feedConfig,
|
feedData.feedConfig,
|
||||||
feedData.emails,
|
feedData.emails,
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ describe("JSON Feed Route", () => {
|
|||||||
const res = await testApp.request("/empty-feed", {}, mockEnv);
|
const res = await testApp.request("/empty-feed", {}, mockEnv);
|
||||||
const link = res.headers.get("Link") ?? "";
|
const link = res.headers.get("Link") ?? "";
|
||||||
expect(link).toContain(`rel="hub"`);
|
expect(link).toContain(`rel="hub"`);
|
||||||
expect(link).toContain(`rel="self"`);
|
expect(link).toContain(
|
||||||
|
`<https://${mockEnv.DOMAIN}/json/empty-feed>; rel="self"`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("body parses as JSON with jsonfeed version 1.1", async () => {
|
it("body parses as JSON with jsonfeed version 1.1", async () => {
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ import { Context } from "hono";
|
|||||||
import { Env } from "../types";
|
import { Env } from "../types";
|
||||||
import { generateJsonFeed } from "../infrastructure/feed-generator";
|
import { generateJsonFeed } from "../infrastructure/feed-generator";
|
||||||
import { fetchFeedData } from "../application/feed-fetcher";
|
import { fetchFeedData } from "../application/feed-fetcher";
|
||||||
import { baseUrl } from "../infrastructure/urls";
|
import { baseUrl, feedJsonUrl } from "../infrastructure/urls";
|
||||||
import { isExpired } from "../domain/feed";
|
import { isExpired } from "../domain/feed";
|
||||||
import { FeedId } from "../domain/value-objects/feed-id";
|
import { FeedId } from "../domain/value-objects/feed-id";
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export async function handle(c: Context<{ Bindings: Env }>): Promise<Response> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base = baseUrl(c.env);
|
const base = baseUrl(c.env);
|
||||||
const selfUrl = new URL(c.req.url).origin + `/json/${feedId}`;
|
const selfUrl = feedJsonUrl(feedId, c.env);
|
||||||
const jsonFeed = generateJsonFeed(
|
const jsonFeed = generateJsonFeed(
|
||||||
feedData.feedConfig,
|
feedData.feedConfig,
|
||||||
feedData.emails,
|
feedData.emails,
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ describe("RSS Feed Route", () => {
|
|||||||
const res = await testApp.request("/empty-feed", {}, mockEnv);
|
const res = await testApp.request("/empty-feed", {}, mockEnv);
|
||||||
const link = res.headers.get("Link") ?? "";
|
const link = res.headers.get("Link") ?? "";
|
||||||
expect(link).toContain(`rel="hub"`);
|
expect(link).toContain(`rel="hub"`);
|
||||||
expect(link).toContain(`rel="self"`);
|
expect(link).toContain(
|
||||||
|
`<https://${mockEnv.DOMAIN}/rss/empty-feed>; rel="self"`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ export async function handle(c: Context<{ Bindings: Env }>): Promise<Response> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base = baseUrl(c.env);
|
const base = baseUrl(c.env);
|
||||||
const selfUrl = new URL(c.req.url).origin + `/rss/${feedId}`;
|
const selfUrl = feedRssUrl(feedId, c.env);
|
||||||
const rssXml = generateRssFeed(
|
const rssXml = generateRssFeed(
|
||||||
feedData.feedConfig,
|
feedData.feedConfig,
|
||||||
feedData.emails,
|
feedData.emails,
|
||||||
|
|||||||
Reference in New Issue
Block a user