Javascript 正则表达式解析 URL/链接到它的语义部分

问题描述 投票:0回答:1

对于这组示例 URL/链接,提供 URL/链接的所有语义组件:

https://google.com:443 - https:// is the protocol, :443 is the port
cdn.ajax.com - cdn is the service, ajax.com is the domain, cdn.ajax.com is the FQDN
www.clients6.gc.google.com/project - clients6.gc is the subdomain, /project is the path
www.google.com/?query=x&#hash=y - ?query=x& is the query string and #hash=y is the hash string

我很高兴不解析用户/密码(不要这样做 - 安全性差)或查询参数(那些是特定于实现的,即一些 Java CGI 工具包使用

;
而不是
&
)。

浏览器会在地址栏中删除 www 和其他服务类型前缀,因此服务类型前缀不属于子域现在已成为事实上的标准。除非你是 DNS 管理员。

大多数浏览器、电话、应用程序等都会处理

www.
和其他常见的网络服务子域前缀,如
https://www.
等,因此这应该遵循该事实上的标准。

所以,要清楚,对于所有这些形式:

www.sub.domain.google.com/path?query=x&#hash=y
https://www.sub.domain.google.com/path?query=x&#hash=y
https://www.sub.domain.google.com:443/path?query=x&#hash=y

语义链接解析器应响应:

{
  "protocol": "https://",
  "fqdn": "www.sub.domain.google.com",
  "service": "www",
  "subdomain": "sub.domain", /* no www. */
  "domain": "google.com",
  "port": "443", /* optional */
  "path": "/path",
  "query": "query=x&",
  "hash": "hash=y"
}
javascript regex parsing url
1个回答
0
投票

使用 MDN Groups and Backreferences docs 和 Regex101 在线正则表达式创作/测试工具,我发现这个解决方案使用 Look-Forward, Non-Capturing, and Named Capturing Groups:

var URL = "https://www.sub.domain.google.com:443/maps/place/Arc+De+Triomphe/@48.8737917,2.2928388,17z?query=1&foo#hash";

var parts = URL.match(/^(?<protocol>https?:\/\/)?(?=(?<fqdn>[^:/]+))(?:(?<service>www|ww\d|cdn|mail|pop\d+|ns\d+|git)\.)?(?:(?<subdomain>[^:/]+)\.)*(?<domain>[^:/]+\.[a-z0-9]+)(?::(?<port>\d+))?(?<path>\/[^?]*)?(?:\?(?<query>[^#]*))?(?:#(?<hash>.*))?/i).groups 

console.log(parts)

产量...

{
  "protocol": "https://",
  "fqdn": "www.sub.domain.google.com",
  "service": "www",
  "subdomain": "sub.domain",
  "domain": "google.com",
  "port": "443",
  "path": "/maps/place/Arc+De+Triomphe/@48.8737917,2.2928388,17z",
  "query": "query=1&foo",
  "hash": "hash"
}

Pointy 指出,大多数浏览器都提供了一个 URL 类,用于将 URL 解析到它们的组件中。

console.log(new URL('www.google.com:443/path?query#hash')

产量...

URL {origin: 'null', protocol: 'www.google.com:', username: '', password: '', host: '', …}
hash: "#hash"
host: ""
hostname: ""
href: "www.google.com:443/path?query#hash"
origin: "null"
password: ""
pathname: "443/path"
port: ""
protocol: "www.google.com:"
search: "?query"
searchParams: URLSearchParams {}
username: ""
[[Prototype]]: URL

如果您要测试协议的字符串并在它丢失时添加它,那么它会起作用,但您可能会发现处理它的神奇属性具有挑战性,因为 URL 类实例拒绝被克隆或迭代。

const link = 'www.sub.domain.google.com:443/path?query=1#hash';

function parseLink(link){
  link.match(/^[a-z]+:/) || (link = 'https://' + link);
  var u = new URL(link);
  var m = u.host.match(/^(?:(?<service>www|ww\d|cdn|mail|pop\d+|ns\d+|git)\.)?(?:(?<subdomain>[^:/]+)\.)*(?<domain>[^:/]+\.[a-z0-9]+)/).groups;
  return {
    fqdn:u.host,
    domain:m.domain,
    subdomain:m.subdomain,
    service:m.service,
    path:u.pathname,
    port:u.port,
    query:u.search,
    hash:u.hash,
    params:Object.fromEntries(u.searchParams.entries())
  }
}
console.log(parseLink(link))

产量...

{
  "fqdn": "www.sub.domain.google.com",
  "domain": "google.com",
  "subdomain": "sub.domain",
  "service": "www",
  "path": "/path",
  "port": "",
  "query": "?query=1",
  "hash": "#hash",
  "params": {
    "query": "1"
  }
}

请注意,它会折叠(默认)端口值。

我加入了查询参数来演示 Chrome 110 损坏的 .getAll() 方法的变通方法,希望这能让别人头疼。

© www.soinside.com 2019 - 2024. All rights reserved.