转换绝对或相对URL,如" example.com/profile "为绝对URL,包括协议.<



我想让用户可以选择在输入字段中输入URL。目前它是非常严格的,因为它只接受像这样的绝对url:https://example.com/a.profile.

用户给出的反馈是,他们也希望能够像这样键入一个相对URL:example.com/a.profilewww.example.com/a.profile

如何获取任意的相对URL或绝对URL并确保输出是绝对URL?可以假定https:协议适用于所有url。

不要乱用正则表达式。使用URLAPI代替:

// Solution:
const asAbsoluteURL = (url, base = location) => {
let absoluteURL;

try {
absoluteURL = new URL(url);
}
catch {
absoluteURL = new URL(`//${url}`, base);
}

return absoluteURL;
};
// Usage:
const absoluteURL1 = asAbsoluteURL("example.com");
const absoluteURL2 = asAbsoluteURL("example.com", "http://something");
const absoluteURL3 = asAbsoluteURL("https://example.com");
console.log({    // Run this snippet and look into your browser console
absoluteURL1,  //   for the results (hit [F12]).
absoluteURL2,
absoluteURL3,
"1. If you want strings": "use concatenation: " + absoluteURL1,
"2. Alternatively": `use template literals: ${absoluteURL2}`,
"3. Or use the String function explicitly": String(absoluteURL3)
});
// Interactive demonstration:
addEventListener("input", () => {
const relativeURL = document.getElementById("relativeURL").value,
baseURL = document.getElementById("baseURL").value || location;
let result;

try {
result = formatCode`Relative URL ${relativeURL} is converted to absolute URL ${asAbsoluteURL(relativeURL, baseURL)}.`
}
catch {
result = formatCode`Either the relative URL ${relativeURL} is not a valid relative URL or the base URL ${baseURL} is not a valid absolute URL itself.`;
}

document.getElementById("output").replaceChildren(...result);
});
const formatCode = (text, ...codeTexts) => text.flatMap((text, index) => [ text, Object.assign(document.createElement("code"), { textContent: codeTexts[index] }) ]).slice(0, -1);
#output { margin-top: 0.4em; line-height: 1.4em; white-space: pre-wrap; }
code { background: #ddd; padding: 0.2em 0.5em; border-radius: 0.2em; }
<input id="relativeURL" type="text" placeholder="example.com">
<input id="baseURL" type="text" placeholder="https://example.com">
<div id="output">Type a relative URL in the left input and an absolute URL as a base in the right input (or leave it blank to use the current location).</div>

此代码只是尝试new URL("您的URL")。这只适用于绝对url,所以如果它工作,伟大的!返回它。

否则,它会抛出一个错误,但是对于try-catch,我们只是捕获它并尝试下一个选项:new URL("//您的URL", base)。第二个参数是一个绝对URL基,用于非绝对URL1。提供了有效的第二个参数后,第一个参数现在可以是一个相对URL。如果一个相对URL以//开头,它将被解释为协议相对URL,因此下一个组件(URL字符串)必须是主机名。

此处使用的base与当前的location相同;在上面的Stack代码片段中,它是"https://stacksnippets.net/js"。您可以提供任何基,如"http://example.com""http://localhost",甚至"ftp://anything"作为asAbsoluteURL的第二个参数。

tbody> <<tr>
Call Result (URL object with thishref)
asAbsoluteURL("example.com")"https://example.com/"
asAbsoluteURL("//example.com")"https://example.com/"
asAbsoluteURL("www.example.com")"https://www.example.com/"
asAbsoluteURL("https://example.com")"https://example.com/"
asAbsoluteURL("example.com", "http://localhost")"http://example.com/"

我现在实现了下面的类,尽管我不确定是否考虑了所有的边缘情况。但也许它可以帮助未来的用户。

const FULL_URL_REGEX =
/(http|https)://(w+:{0,1}w*@)?(S+)(:[0-9]+)?(.ww+)(/|/([w#!:.?+=&%@!-/]))?/;
const HALF_URL_REGEX =
/(w+:{0,1}w*@)?(S+)(:[0-9]+)?(.ww+)(/|/([w#!:.?+=&%@!-/]))?/;
const ASSUME_PROTOCOL = 'https';
export class URLTools {
public static urlIsValid(url: string): boolean {
return FULL_URL_REGEX.test(url) || HALF_URL_REGEX.test(url);
}
public static guaranteeFullUrl(potentiallyHalfUrl: string) {
if (HALF_URL_REGEX.test(potentiallyHalfUrl)) {
return `${ASSUME_PROTOCOL}://${potentiallyHalfUrl}`;
} else if (FULL_URL_REGEX.test(potentiallyHalfUrl)) {
return potentiallyHalfUrl;
} else {
throw Error('Invalid URL');
}
}
}

最新更新