Skip to content

azu/url-cheatsheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

url-cheatsheet

URL manipulation cheatsheet for JavaScript.

DO NOT: concat url and user input without escape

Please DO NOT concat url and user input without escape

// DO NOT
const name = "<user input>";
const url = `https://example.com/user/${name}`;
console.log(url); // => "https://example.com/user/<user input>"

This code may have directory traversal vulnerability. You should escape the name by encodeURIComponent.

// DO
const name = "<user input>";
const url = `https://example.com/user/${encodeURIComponent(name)}`;
console.log(url); // => "https://example.com/user/%3Cuser%20input%3E"

Addtionaly, You should reject . and .. as a name. Because encodeURIComponent("..") is .., it may have directory traversal vulnerability.

// DO
const name = "<user input>";
if (name === ".." || name === ".") {
  throw new Error("Invalid name");
}
const url = `https://example.com/user/${encodeURIComponent(name)}`;
console.log(url); // => "https://example.com/user/%3Cuser%20input%3E"

DO NOT: concat parameter and user input without escape

Please DO NOT concat parameter and user input without escape

// DO NOT
const query = "<user input>";
const url = `https://example.com?q=${query}`;
console.log(url); // => "https://example.com?q=<user input>"

This example does not consider that query includes & or ? that is required to escape. You should escape the query by encodeURIComponent.

// DO
const query = "<user input>";
const url = `https://example.com?q=${encodeURIComponent(query)}`;
console.log(url); // => "https://example.com?q=%3Cuser%20input%3E"

Or, You can use URLSearchParams() that escape each parameters automatically.

Base URL + Path

Use new URL(pathname, base).

  • keywords: url-join, join path
const base = "https://example.com";
const pathname = "/path/to/page";
const result = new URL(pathname, base);
console.log(result.toString()); // => "https://example.com/path/to/page"

If the pathname include user input, you should escape it by encodeURIComponent.

const base = "https://example.com/";
const name = "<user input>";
const result = new URL(`/user/${encodeURIComponent(name)}`, base);
console.log(result.toString()); // => "https://example.com/user/%3Cuser%20input%3E"

Addtionaly, You should reject . and .. as a name. Because encodeURIComponent("..") is .., it may have directory traversal vulnerability.

// DO
const base = "https://example.com/";
const name = "<user input>";
if (name === ".." || name === ".") {
  throw new Error("Invalid name");
}
const result = new URL(`/user/${encodeURIComponent(name)}`, base);
console.log(result.toString()); // => "https://example.com/user/%3Cuser%20input%3E"

Get parameter from URL

Use URL and URLSearchParams#get

const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
const q = url.searchParams.get("q");
console.log(q); // => "query"

Get multiple parameters as array from URL

Use URL and URLSearchParams#getAll

const inputURL = "https://example.com/?q=query&lang=en_US&lang=ja_JP";
const url = new URL(inputURL);
const langs = url.searchParams.getAll("lang");
console.log(langs); // ["en_US", "ja_JP"]

Add parameters to URL

Use URLSearchParams

const q = "query";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
const params = new URLSearchParams({
  q,
  page,
});
console.log(url + "?" + params); // => "https://example.com/?q=query&page=1"

or

const q = "query";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
url.search = new URLSearchParams({
  q,
  page,
});
console.log(url.toString()); // => "https://example.com/?q=query&page=1"

đź“ť URLSearchParams escape each parameter automtically.

const q = "<user input>";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
url.search = new URLSearchParams({
  q,
  page,
});
console.log(url.toString()); // => "https://example.com/?q=%3Cuser+input%3E&page=1"

Update parameter of URL

Use URL's searchParams property.

const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
url.searchParams.set("q", "update");
console.log(url.toString()); // => "https://example.com/?q=update&page=1"

Remove parameter from URL

Use URL and URLSearchParams

const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
url.searchParams.delete("q");
console.log(url.toString()); // => "https://example.com/?page=1"

Filter parameters

Allow only a and d parameters.

  • keywords: pick, white list, allow list
const base = "https://example.com/?a=1&b=2&c=3&d=4";
const url = new URL(base);
const allowedParameterNames = ["a", "d"];
url.search = new URLSearchParams(
  Array.from(url.searchParams).filter(([key, value]) => {
    return allowedParameterNames.includes(key);
  })
);
console.log(url.toString()); // => "https://example.com/?a=1&d=4"

Check URL is Absolute-URL

new URL(urlString) throw an error when parsing relative url string. As a result, you can use URL for checking URL is absolute-URL that starts with a schema like https:

const isValidURL = (urlString) => {
  try {
    new URL(urlString); // if `urlString` is invalid, throw an erorr
    return true;
  } catch {
    return false;
  }
};
console.log(isValidURL("https://example.com")); // => true
console.log(isValidURL("https/example.com")); // => false

Check URL is HTTP

Check URL's protocol property.

const isHttpURL = (urlString) => {
  try {
    const url = new URL(urlString); // if `urlString` is invalid, throw an erorr
    return url.protocol === "http:" || url.protocol === "https:";
  } catch {
    return false;
  }
};
console.log(isHttpURL("http://example.com")); // => true
console.log(isHttpURL("https://example.com")); // => true
console.log(isHttpURL("ftp://example.com")); // => false
console.log(isHttpURL("https/example.com")); // => false