fix: add X-Robots-Tag noindex for staging, remove dead comment (TDD)
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 19m3s

This commit is contained in:
Hoid 2026-03-08 17:03:37 +01:00
parent 7206cb518d
commit b70ed49c15
2 changed files with 63 additions and 3 deletions

View file

@ -0,0 +1,55 @@
import { describe, it, expect } from "vitest";
import request from "supertest";
import { app } from "../index.js";
describe("Staging noindex protection", () => {
it("should add X-Robots-Tag: noindex when hostname contains 'staging'", async () => {
const res = await request(app)
.get("/")
.set("Host", "staging.docfast.dev");
expect(res.headers["x-robots-tag"]).toBe("noindex, nofollow");
});
it("should NOT add X-Robots-Tag on production hostname", async () => {
const res = await request(app)
.get("/")
.set("Host", "docfast.dev");
expect(res.headers["x-robots-tag"]).toBeUndefined();
});
it("should add X-Robots-Tag on staging for API endpoints too", async () => {
const res = await request(app)
.get("/health")
.set("Host", "staging.docfast.dev");
expect(res.headers["x-robots-tag"]).toBe("noindex, nofollow");
});
});
describe("404 page", () => {
it("should serve branded HTML 404 for non-API paths", async () => {
const res = await request(app).get("/nonexistent-page");
expect(res.status).toBe(404);
expect(res.text).toContain("404");
expect(res.text).toContain("Page Not Found");
expect(res.text).toContain("DocFast");
});
it("should serve JSON 404 for API paths", async () => {
const res = await request(app).get("/v1/nonexistent");
expect(res.status).toBe(404);
expect(res.body.error).toContain("Not Found");
});
});
describe("Dead code cleanup", () => {
it("should not have empty email verification comment in index.ts", async () => {
const fs = await import("fs");
const content = fs.readFileSync(new URL("../index.ts", import.meta.url), "utf-8");
expect(content).not.toContain("// Email verification endpoint\n\n");
});
});

View file

@ -56,6 +56,14 @@ app.use((_req, res, next) => {
// Compression // Compression
app.use(compressionMiddleware); app.use(compressionMiddleware);
// Block search engine indexing on staging
app.use((req, res, next) => {
if (req.hostname.includes("staging")) {
res.setHeader("X-Robots-Tag", "noindex, nofollow");
}
next();
});
// Differentiated CORS middleware // Differentiated CORS middleware
app.use((req, res, next) => { app.use((req, res, next) => {
const isAuthBillingRoute = req.path.startsWith('/v1/signup') || const isAuthBillingRoute = req.path.startsWith('/v1/signup') ||
@ -214,9 +222,6 @@ app.post("/admin/cleanup", authMiddleware, adminAuth, async (_req: any, res: any
} }
}); });
// Email verification endpoint
// Landing page // Landing page
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));