Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions nitro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,22 @@ export default defineConfig({
serverDir: "./server",
baseURL: "/base",
publicAssets: [{ baseURL: "/_dist", dir: "./public/_dist", maxAge: 60 * 60 * 24 * 365 }],
routeRules: {
"/tests/headers": {
headers: {
"x-nitro-test": "hello",
"x-nitro.test-2": "dotted",
"x-nitro-spaced": "hello world from nitro",
"x-nitro-long": "a".repeat(1024),
"x-nitro-special": "a!#$%&'*+-.^_`|~b",
"x-nitro-num": "42",
},
},
"/redirect-source": {
redirect: "/base/redirect-target",
},
"/basic-auth-protected": {
basicAuth: { username: "admin", password: "nitrorunseverywhere" },
},
Comment on lines +21 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid committing plaintext credentials, even for demo auth.

password: "nitrorunseverywhere" is committed to the repo. For a public test-deployment project this is likely intentional (the credential must be known to exercise the test), but it's worth noting: once public it can never be reused for anything sensitive, and it trains a pattern of inline secrets. Consider sourcing it from an env var with a documented default, e.g. password: process.env.BASIC_AUTH_PASSWORD ?? "nitrorunseverywhere", so real deployments can override it without code changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nitro.config.ts` around lines 21 - 23, The committed plaintext demo password
is in the nitro config under the "/basic-auth-protected" route
(basicAuth.username/basicAuth.password); change the code to read the password
from an environment variable (e.g., BASIC_AUTH_PASSWORD) with the existing
literal as a documented default so deployments can override it, update any docs
or .env.example to show the new env var, and ensure the code still falls back to
the demo string when the env var is not set.

},
});
5 changes: 5 additions & 0 deletions server/routes/basic-auth-protected.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineEventHandler } from "nitro/h3";

export default defineEventHandler((event) => {
return event.context.basicAuth?.username ?? "no-auth";
});
11 changes: 10 additions & 1 deletion server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ const baseURL = "/base/";

const withBase = (p: string) => baseURL + p.replace(/^\//, "");

const tests = ["api", "form-data", "multipart-form-data", "sourcemap"];
const tests = [
"api",
"basic-auth",
"form-data",
"headers",
"meta",
"multipart-form-data",
"redirect",
"sourcemap",
];

const manualTests = ["env", "node-compat", "headers"];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Duplicate test name in manualTests.

"headers" is now present in both the automated tests array (line 13) and manualTests (line 20). Since automated tests already render an iframe with id="tests-headers" and assert PASS/FAIL, listing it again under manual tests is redundant and may confuse users. Consider removing it from manualTests.

Proposed fix
-const manualTests = ["env", "node-compat", "headers"];
+const manualTests = ["env", "node-compat"];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const manualTests = ["env", "node-compat", "headers"];
const manualTests = ["env", "node-compat"];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/routes/index.ts` at line 20, The manualTests array contains a
duplicate entry "headers" which is already present in the automated tests array
and rendered/checked via the iframe with id "tests-headers"; remove "headers"
from the manualTests array (the constant manualTests) so only automated tests
include it, leaving manualTests = ["env", "node-compat"] (update any related
UI/labels if they reference manualTests to ensure no leftover references to
"headers").


Expand Down
3 changes: 3 additions & 0 deletions server/routes/redirect-target.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineEventHandler } from "nitro/h3";

export default defineEventHandler(() => "REDIRECTED");
18 changes: 18 additions & 0 deletions server/routes/tests/basic-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineTestHandler } from "../../utils/test";

// Route rule in nitro.config.ts protects /base/basic-auth-protected with basic auth.
// The handler echoes `event.context.basicAuth.username`, which is only populated
// when the basicAuth route rule runs successfully. We avoid triggering a 401
// response here because browsers show a native auth popup on 401 + WWW-Authenticate.
export default defineTestHandler(
"basic-auth",
() => "test-page",
async ({ assert }) => {
const res = await fetch("/base/basic-auth-protected", {
headers: { Authorization: "Basic " + btoa("admin:nitrorunseverywhere") },
});
assert(res.status === 200, `Expected 200 with valid credentials, got: ${res.status}`);
const text = await res.text();
assert(text === "admin", `Expected body "admin" (echoed from basicAuth context), got: ${text}`);
},
);
38 changes: 38 additions & 0 deletions server/routes/tests/headers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { defineTestHandler } from "../../utils/test";

// Route rule in nitro.config.ts sets multiple response headers on this path
// to exercise name/value edge cases that should work across all providers.
export default defineTestHandler(
"headers",
() => "OK",
async ({ assert, log }) => {
const res = await fetch("");

const cases: Array<[string, string]> = [
// Baseline ASCII
["x-nitro-test", "hello"],
// Dots, dashes, digits in the name
["x-nitro.test-2", "dotted"],
// Internal spaces in value (legal per RFC 9110)
["x-nitro-spaced", "hello world from nitro"],
// Long value (1 KB)
["x-nitro-long", "a".repeat(1024)],
// Special-but-legal tchars in value
["x-nitro-special", "a!#$%&'*+-.^_`|~b"],
// Numeric-like value
["x-nitro-num", "42"],
];

for (const [name, expected] of cases) {
const actual = res.headers.get(name);
log(`${name}: ${actual}`);
assert(actual === expected, `Expected ${name}=${expected}, got: ${actual}`);
}

// Case-insensitive lookup must work regardless of how the runtime preserves case.
assert(
res.headers.get("X-NITRO-TEST") === "hello",
"Expected case-insensitive header lookup to work",
);
},
);
16 changes: 16 additions & 0 deletions server/routes/tests/meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { version } from "nitro/meta";
import { defineTestHandler } from "../../utils/test";

export default defineTestHandler(
"meta",
() => ({ version }),
async ({ assert, log }) => {
const res = await fetch("").then((r) => r.json());
log(`Nitro version: ${res.version}`);
assert(
typeof res.version === "string" && res.version.length > 0,
`Expected non-empty version string, got: ${res.version}`,
);
assert(/^\d+\.\d+\.\d+/.test(res.version), `Expected semver-like version, got: ${res.version}`);
},
);
13 changes: 13 additions & 0 deletions server/routes/tests/redirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineTestHandler } from "../../utils/test";

// Route rule in nitro.config.ts redirects /base/redirect-source to /base/redirect-target.
export default defineTestHandler(
"redirect",
() => "test-page",
async ({ assert }) => {
const res = await fetch("/base/redirect-source");
const text = await res.text();
assert(res.redirected === true, `Expected redirected=true, got: ${res.redirected}`);
assert(text === "REDIRECTED", `Expected body "REDIRECTED", got: ${text}`);
},
);
Loading