summaryrefslogtreecommitdiff
path: root/cgithub/src
diff options
context:
space:
mode:
Diffstat (limited to 'cgithub/src')
-rw-r--r--cgithub/src/app.test.ts20
-rw-r--r--cgithub/src/app.ts10
2 files changed, 29 insertions, 1 deletions
diff --git a/cgithub/src/app.test.ts b/cgithub/src/app.test.ts
index 5474f8d..59ed352 100644
--- a/cgithub/src/app.test.ts
+++ b/cgithub/src/app.test.ts
@@ -110,6 +110,26 @@ describe("redirects to GitHub", () => {
assert.doesNotMatch(body, /<script/);
});
+ // Same-origin requests are mostly subresources, which render an HTML page as
+ // a broken image rather than following its refresh.
+ it("should redirect over HTTP when the referer is one of our own pages", async () => {
+ const res = await app.request("http://cgithub.example/a/b/c?x=1", {
+ headers: { Referer: "http://cgithub.example/a/b" },
+ });
+
+ assert.strictEqual(res.status, 302);
+ assert.strictEqual(res.headers.get("location"), "https://github.com/a/b/c?x=1");
+ });
+
+ it("should use a meta refresh when the referer is another site", async () => {
+ const res = await app.request("http://cgithub.example/a/b/c?x=1", {
+ headers: { Referer: "https://github.example/a/b" },
+ });
+
+ assert.strictEqual(res.status, 200);
+ assert.strictEqual(res.headers.get("location"), null);
+ });
+
it("should redirect unhandled search types", async () => {
const res = await app.request(
"http://cgithub.example/actions/deploy-pages/search?q=x&type=code",
diff --git a/cgithub/src/app.ts b/cgithub/src/app.ts
index e27db59..9781a98 100644
--- a/cgithub/src/app.ts
+++ b/cgithub/src/app.ts
@@ -29,8 +29,16 @@ export function createApp(eta: Eta) {
const app = new Hono();
// Use a meta refresh to avoid redirect loops in certain situations; we become
- // the initiator origin even if we are the target of a redirection.
+ // the initiator origin even if we are the target of a redirection. Requests
+ // coming from one of our own pages are already past that hazard, and are
+ // often subresources (an <img> in a rendered README) that can't do anything
+ // with an HTML page, so those get a real HTTP redirect.
function redirectToGitHub(c: Context, location: string) {
+ const referer = c.req.header("Referer");
+ if (referer && URL.parse(referer)?.origin === new URL(c.req.url).origin) {
+ return c.redirect(location);
+ }
+
c.header("Referrer-Policy", "no-referrer");
return c.html(eta.render("redirect.eta", { location }));
}