Step 3: Validate the target URL
Never trust what users send. The URL class parses addresses for you and throws on nonsense. After parsing, check the protocol: only http: and https: are allowed. Allowing javascript: or file: targets would turn your shortener into an attack tool. Also limit the length, so nobody stores megabytes.
ExampleNode.js
function parseTarget(input) {
if (typeof input !== "string" || input.length > 2000) return { error: "url must be a string of at most 2000 characters" };
let url;
try {
url = new URL(input);
} catch {
return { error: "not a valid URL" };
}
// Only web links. A "javascript:" or "file:" link in a redirect would be an attack.
if (url.protocol !== "http:" && url.protocol !== "https:") return { error: "only http and https links are allowed" };
return { url: url.toString() };
}
const tests = [
"https://example.com/page?x=1",
"http://localhost:3000",
"javascript:alert(1)",
"file:///etc/passwd",
"not a url",
"",
42,
"https://" + "a".repeat(2100),
];
for (const t of tests) {
const r = parseTarget(t);
const shown = typeof t === "string" ? (t.length > 30 ? t.slice(0, 27) + "..." : t) : String(t);
console.log(JSON.stringify(shown).padEnd(34), r.url ? "OK " + r.url : "ERR " + r.error);
}Output
"https://example.com/page?x=1" OK https://example.com/page?x=1 "http://localhost:3000" OK http://localhost:3000/ "javascript:alert(1)" ERR only http and https links are allowed "file:///etc/passwd" ERR only http and https links are allowed "not a url" ERR not a valid URL "" ERR not a valid URL "42" ERR url must be a string of at most 2000 characters "https://aaaaaaaaaaaaaaaaaaa..." ERR url must be a string of at most 2000 characters
Notice that parseTarget returns an object with either url or error instead of throwing: callers handle both cases in a plain if.
Quick check
Why reject javascript: URLs?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.