从 URL 获取协议、域和端口

Posted

技术标签:

【中文标题】从 URL 获取协议、域和端口【英文标题】:Get protocol, domain, and port from URL 【发布时间】:2011-10-19 23:17:06 【问题描述】:

我需要从给定的 URL 中提取完整的协议、域和端口。例如:

https://localhost:8181/ContactUs-1.0/contact?lang=it&report_type=consumer
>>>
https://localhost:8181

【问题讨论】:

对于那些寻找 URL 不是当前位置的答案的读者,请查看以下已接受的答案 【参考方案1】:

先获取当前地址

var url = window.location.href

然后只解析那个字符串

var arr = url.split("/");

你的网址是:

var result = arr[0] + "//" + arr[2]

希望对你有帮助

【讨论】:

这适用于 location 对象不可用的 URL 字符串(浏览器外部的 js!) David Calhoun 的 answer 使用内置解析器(如 location),但可用于 any url。看看它是不是很整洁。 或者直接把它变成单行:window.location.href.split('/').slice(0, 3).join('/') 你如何在节点上做到这一点? window.location.origin【参考方案2】:
const full = location.protocol + '//' + location.host;

【讨论】:

@Randomblue 怎么样?你会得到about://。但是,我很想知道,about:blank 的用例是什么?我不确定是否有浏览器在about:blank 中注入插件资源,但似乎这可能是唯一的用例。 如果你有一个 URL 字符串,这根本不起作用,对吧? (即您需要 at location 才能工作) 抱歉回复晚了,@NickT。是的,它不会那样做。请使用nice solution provided by David 这个答案应该被选为正确答案。它很干净并且使用标准的位置对象。 你不能用location.host代替location.hostname + location.port吗?【参考方案3】:

出于某种原因,所有的答案都是矫枉过正。这就是全部:

window.location.origin

更多详情可以在这里找到:https://developer.mozilla.org/en-US/docs/Web/API/window.location#Properties

【讨论】:

仅供参考,当所有流行的浏览器都实现它时,我相信这在未来会很棒,然而,目前情况并非如此:developer.mozilla.org/en-US/docs/Web/API/…根据我的研究,在撰写本文时,只有最新版本的 Firefox 和 WebKit 浏览器支持 origin 属性。 只是为了完成:位置是defined on html5,它实现了URLUtils接口,即defined on WHATWG并包含origin属性。 Hello from 2015.. 不幸的是,根据 MDN 上的this compatibility table,URLUtils 仍未在所有浏览器中正确实现。然而,似乎对 origin 属性的支持比 2013 年稍好,它仍然是 not fit for production,因为它在 Safari 中没有正确实现。对不起各位:( 它在 IE 中也不起作用,它返回“未定义”。 您好,从 2020 年开始:它现在适用于所有浏览器,Opera 未知。此信息来自这里:developer.mozilla.org/en-US/docs/Web/API/Window/…【参考方案4】:

确实,window.location.origin 在遵循标准的浏览器中运行良好,但你猜怎么着。 IE 没有遵循标准。

因此,这就是我在 IE、FireFox 和 Chrome 中的工作方式:

var full = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: '');

但对于可能导致冲突的未来增强功能,我在“位置”对象之前指定了“窗口”引用。

var full = window.location.protocol+'//'+window.location.hostname+(window.location.port ? ':'+window.location.port: '');

【讨论】:

【参考方案5】:
var http = location.protocol;
var slashes = http.concat("//");
var host = slashes.concat(window.location.hostname);

【讨论】:

【参考方案6】:

正如已经提到的,目前还没有完全支持window.location.origin,但我不想使用它或创建一个新的变量来使用,我更喜欢检查它,如果它没有设置为设置它。

例如;

if (!window.location.origin) 
  window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');

实际上我几个月前写过这个A fix for window.location.origin

【讨论】:

这是我第一次知道window.location.origin 存在。谢谢你。 ^^【参考方案7】:

protocol 属性设置或返回当前 URL 的协议,包括冒号 (:)。

这意味着如果您只想获取 HTTP/HTTPS 部分,您可以执行以下操作:

var protocol = window.location.protocol.replace(/:/g,'')

对于您可以使用的域:

var domain = window.location.hostname;

你可以使用的端口:

var port = window.location.port;

请记住,如果在 URL 中不可见,端口将是一个空字符串。例如:

http://example.com/ 将为端口返回 "" http://example.com:80/ 将为端口返回 80

如果你没有使用端口时需要显示 80/443

var port = window.location.port || (protocol === 'https' ? '443' : '80');

【讨论】:

【参考方案8】:

这些答案似乎都没有完全解决这个问题,它需要一个任意的 url,而不是当前页面的 url。

方法一:使用 URL API(注意:不支持 IE11)

您可以使用URL API(IE11 不支持,但可用everywhere else)。

这也使访问search params 变得容易。另一个好处:它可以在 Web Worker 中使用,因为它不依赖于 DOM。

const url = new URL('http://example.com:12345/blog/foo/bar?startIndex=1&pageSize=10');

方法2(老方法):在DOM中使用浏览器的内置解析器

如果您也需要它在旧版浏览器上工作,请使用它。

//  Create an anchor element (note: no need to append this element to the document)
const url = document.createElement('a');
//  Set href to any path
url.setAttribute('href', 'http://example.com:12345/blog/foo/bar?startIndex=1&pageSize=10');

就是这样!

浏览器的内置解析器已经完成了它的工作。现在您可以获取您需要的部分(请注意,这适用于上述两种方法):

//  Get any piece of the url you're interested in
url.hostname;  //  'example.com'
url.port;      //  12345
url.search;    //  '?startIndex=1&pageSize=10'
url.pathname;  //  '/blog/foo/bar'
url.protocol;  //  'http:'

奖励:搜索参数

您可能还想拆分搜索 url 参数,因为 '?startIndex=1&pageSize=10' 本身并不太有用。

如果您使用上述方法 1(URL API),您只需使用 searchParams getter:

url.searchParams.get('startIndex');  // '1'

或者获取所有参数:

function searchParamsToObj(searchParams) 
  const paramsMap = Array
    .from(url.searchParams)
    .reduce((params, [key, val]) => params.set(key, val), new Map());
  return Object.fromEntries(paramsMap);

searchParamsToObj(url.searchParams);
// ->  startIndex: '1', pageSize: '10' 

如果您使用方法 2(旧方法),您可以使用如下方式:

// Simple object output (note: does NOT preserve duplicate keys).
var params = url.search.substr(1); // remove '?' prefix
params
    .split('&')
    .reduce((accum, keyval) => 
        const [key, val] = keyval.split('=');
        accum[key] = val;
        return accum;
    , );
// ->  startIndex: '1', pageSize: '10' 

【讨论】:

link.protocol 如果我用“google.com”检查anker,我会得到一个“http:”:-(var link = document.createElement('a'); link.setAttribute('href', 'google.com'); console.log(link.protocol) 您是在http 页面上这样做吗?如果未指定,它将从当前位置“继承” 这是一个很棒的答案,应该会得到更多的选票,因为这个答案不仅限于 当前 位置,而且适用于 任何 url,并且因为这个答案使用了浏览器的内置解析器,而不是我们自己构建一个(我们不能希望做得这么好或这么快!)。 谢谢你的这个聪明的把戏!我想补充一件事:hosthostname 都有。前者包括端口(例如localhost:3000),而后者只是主机名(例如localhost)。 这适用于绝对 URL。在相对 URL 和跨浏览器的情况下它会失败。有什么建议吗?【参考方案9】:

主持人

var url = window.location.host;

返回localhost:2679

主机名

var url = window.location.hostname;

返回localhost

【讨论】:

谢谢!!!我不明白为什么 localhost 显示为 localhost/ 而不是 localhost:3000【参考方案10】:
var getBasePath = function(url) 
    var r = ('' + url).match(/^(https?:)?\/\/[^/]+/i);
    return r ? r[0] : '';
;

【讨论】:

考虑解释你的答案。不要假设 OP 可以理解代码不同部分的重要性。【参考方案11】:

尝试使用正则表达式 (Regex),当您想要验证/提取内容,甚至在 javascript 中进行一些简单的解析时,这将非常有用。

正则表达式是:

/([a-zA-Z]+):\/\/([\-\w\.]+)(?:\:(\d0,5))?/

演示:

function breakURL(url)

     matches = /([a-zA-Z]+):\/\/([\-\w\.]+)(?:\:(\d0,5))?/.exec(url);

     foo = new Array();

     if(matches)
          for( i = 1; i < matches.length ; i++) foo.push(matches[i]); 
     

     return foo


url = "https://www.google.co.uk:55699/search?q=http%3A%2F%2F&oq=http%3A%2F%2F&aqs=chrome..69i57j69i60l3j69i65l2.2342j0j4&sourceid=chrome&ie=UTF-8"


breakURL(url);       // [https, www.google.co.uk, 55699] 
breakURL();          // []
breakURL("asf");     // []
breakURL("asd://");  // []
breakURL("asd://a"); // [asd, a, undefined]

现在您也可以进行验证了。

【讨论】:

"一个有效的 RFC 3986 URL 方案必须由一个字母和后跟字母、数字、加号 ("+")、句点 (".") 或连字符 ("- ")." -- ***.com/a/9142331/188833 (这是一个 urn:ietf:rfc:3897 (URI) / urn:ietf:rfc:3897 (IRI) 方案的正则表达式:Python 中 URI/IRI 的一部分:github.com/dgerber/rfc3987/blob/master/rfc3987.py#L147 )【参考方案12】:

具有可配置参数的 ES6 样式。

/**
 * Get the current URL from `window` context object.
 * Will return the fully qualified URL if neccessary:
 *   getCurrentBaseURL(true, false) // `http://localhost/` - `https://localhost:3000/`
 *   getCurrentBaseURL(true, true) // `http://www.example.com` - `https://www.example.com:8080`
 *   getCurrentBaseURL(false, true) // `www.example.com` - `localhost:3000`
 *
 * @param boolean [includeProtocol=true]
 * @param boolean [removeTrailingSlash=false]
 * @returns string The current base URL.
 */
export const getCurrentBaseURL = (includeProtocol = true, removeTrailingSlash = false) => 
  if (!window || !window.location || !window.location.hostname || !window.location.protocol) 
    console.error(
      `The getCurrentBaseURL function must be called from a context in which window object exists. Yet, window is $window`,
      [window, window.location, window.location.hostname, window.location.protocol],
    )
    throw new TypeError('Whole or part of window is not defined.')
  

  const URL = `$includeProtocol ? `$window.location.protocol//` : ''$window.location.hostname$
    window.location.port ? `:$window.location.port` : ''
  $removeTrailingSlash ? '' : '/'`

  // console.log(`The URL is $URL`)

  return URL

【讨论】:

【参考方案13】:

window.location.protocol + '//' + window.location.host

【讨论】:

【参考方案14】:

window.location.origin 就足够了。

【讨论】:

这很容易解决了我的问题。谢谢@intsoumen 感谢您的赞赏@TurkerTunali【参考方案15】:

适用于所有浏览器的简单答案:

let origin;

if (!window.location.origin) 
  origin = window.location.protocol + "//" + window.location.hostname + 
     (window.location.port ? ':' + window.location.port: '');


origin = window.location.origin;

【讨论】:

【参考方案16】:

这是我正在使用的解决方案:

const result = `$ window.location.protocol //$ window.location.host `;

编辑:

要添加跨浏览器兼容性,请使用以下代码:

const result = `$ window.location.protocol //$ window.location.hostname + (window.location.port ? ':' + window.location.port: '') `;

【讨论】:

赞成,但window.location.host 可能不是最好的跨浏览器 谢谢,我在原始答案中添加了跨浏览器兼容性。【参考方案17】:

为什么不使用:

let full = window.location.origin

【讨论】:

在使用现有答案添加旧问题的答案时,解释您的答案带来了哪些新信息以及确认时间的流逝是否会影响答案是很有用的。【参考方案18】:

与ES6 template literals:

const url = `$location.protocol//$location.hostname$location.port?':'+location.port:''`;

document.getElementById("result").innerText = url;
&lt;div id="result"&gt;&lt;/div&gt;

你可以简化为:

const url = `$location.protocol//$location.host`;

document.getElementById("result").innerText = url;
&lt;div id="result"&gt;&lt;/div&gt;

【讨论】:

【参考方案19】:
console.log(`$req.protocol://$req.get('host')/$req.originalUrl`);
req.protocol - 给出你使用的协议(例如HTTPreq.get(host) - 给出主机名和端口号(例如localhost:8080

【讨论】:

以上是关于从 URL 获取协议、域和端口的主要内容,如果未能解决你的问题,请参考以下文章

从 URL 获取协议、域和端口

Django REST 框架。如何获取包含协议、域和路径的页面的完整 url?

如何使用 $location 在工厂中获取当前 url 的协议主机和端口

如何在 Angular Universal 中获取完整的基本 URL(包括服务器、端口和协议)?

.NET - 获取协议、主机和端口

当域和协议匹配时获取 iframe 内容高度,但子域不匹配