简介
解析URLs是网站开发过程中的一项常见任务,也是一项看似简单但可能变得复杂的任务。你很少会遇到这样一个模块,它使解析工作变得如此简单,以至于你不用自己去想很多。
尽管比较年轻(2021年6月发布),但每周有近300万次下载。 parse-url是在JavaScript中解析URL的顶级模块之一。
在这篇文章中,我们将看看它所有的可能性,以及它是如何让我们的生活更轻松的。
一个URL的部分
一个URL有很多部分,所以把它分成零碎的部分而不进行纯粹的字符串解析是一个强大的工具。每个URL都有相同的主要部分,其他部分是可选的,取决于查询或行动。
一个URL的组成元素是
- 方案- 用于识别在互联网上获取资源所使用的协议
- 一些比较流行的协议是。HTTP、HTTPS、IP、ICMP、TCP、UDP,等等。
- 主机--拥有我们要获取的资源的主机的名称(
www.somehost.com) - 路径--位于该主机上的资源的路径(
www.somehost.com/path/to/index.html) - Query string- 包含键值对的字符串(
www.somehost.com/index?key=value&key2=value2)
这些是URL的主要部分,但我们会看到我们可以用parse-url检索更多的内容,而且是以非常可读的、同样可解析的格式检索。
安装和设置parse-url模块
我们首先为我们的迷你项目创建一个文件夹,名为parse_url 。在这个文件夹中,我们可以使用npm 来安装模块。
$ npm i parse-url
为了在我们的代码中使用该模块(在index.js文件中),我们必须将其require 。
const parseUrl = require('parse-url');
就这样,我们就可以开始了!让我们看看这个模块提供了什么。
解析URL
首先,让我们取一个简单的URL。https://www.stackabuse.com.parseUrl 的构造函数接收两个参数:string_url 和normalize ,而normalize 是可选的。
默认情况下,它被设置为false ,并且假定所提供的URL已经被规范化了。当true ,它将非规范化的URL转换为规范化的URL。比如说。
someRandomUrl.com:80 --> http://someRandomUrl.com
这就是所谓的URL规范化。parse-url 模块以normalize-url 模块为基础进行规范化处理,而normalize-url 模块的工作方式与上面所示完全相同。
让我们来解析一个URL。
const url = 'https://www.stackabuse.com/';
const parsedUrl = parseUrl(url);
console.log(parsedUrl)
代码的输出将是JSON格式,它由该URL的元素组成。
{
protocols: [ 'https' ],
protocol: 'https',
port: null,
resource: 'www.stackabuse.com',
user: '',
pathname: '',
hash: '',
search: '',
href: 'https://www.stackabuse.com',
query: [Object: null prototype] {}
}
正如你所看到的,有很多东西被提取出来了,虽然,有些是空的,因为我们提供的URL是很空的。让我们来看看这个JSON中的元素。
protocols- 在URL中使用的协议列表(可以是多个)。protocol- 首先是protocolsport- 一个端口(如果提供的话)resource- 主机user- 主机服务器上的用户*(user@host*)pathname- 资源的路径hash- 如果提供, (哈希值)之后的信息 - 通常是网页上的锚点#search- 一个查询字符串href- 完整的URL
一个有趣的例子是使用GitHub的链接,这也是创建这个模块的初衷之一。与你日常看到的其他URL相比,GitHub的链接可能变得相当复杂,而且可能包括多个协议和用户。
const url = 'git+ssh://git@somehost.com/path/to/resource.git';
const parsedUrl = parseUrl(url);
console.log(parsedUrl)
这就导致了
{
protocols: [ 'git', 'ssh' ],
protocol: 'git',
port: null,
resource: 'somehost.com',
user: 'git',
pathname: '/path/to/resource.git',
hash: '',
search: '',
href: 'git+ssh://git@somehost.com/path/to/resource.git',
query: [Object: null prototype] {}
}
这里的列表协议已经改变,因为有多个协议在使用。然而,在打印出URL信息时,参考的是第一个。我们还可以看到pathname ,现在填写的是资源的路径。
parse-url 的卖点之一是它能很好地处理 Git URLs。
让我们真正地提高URL,包括一个哈希值和几个键值的查询。
const url = 'git+ssh://git@somehost.com:30/path/to/resource.git?key1=value1&key2=value2#anchor';
const parsedUrl = parseUrl(url);
console.log(parsedUrl)
这个例子与之前的例子仅有一点不同,只需填入之前例子中的空值即可。输出结果将是。
{
protocols: [ 'git', 'ssh' ],
protocol: 'git',
port: 30,
resource: 'somehost.com',
user: 'git',
pathname: '/path/to/resource.git',
hash: 'anchor',
search: 'key1=value1&key2=value2',
href: 'git+ssh://git@somehost.com:30/path/to/resource.git?key1=value1&key2=value2#anchor',
query: [Object: null prototype] { key1: 'value1', key2: 'value2' }
}
现在端口、哈希和查询都存在了--我们甚至已经得到了查询的键和值在解析URL时,让解析后的数据以人类可读的格式结构化,并被普遍接受和容易解析是一个真正的帮助。
虽然,这只是返回对象的漂亮打印输出。让我们能够真正使用这些解析过的元素的事实是,它们都是返回对象的字段,我们可以很容易地访问它们。
console.log("The protocols used in the URL are " + parsedUrl.protocols);
console.log("The port used in the URL is " + parsedUrl.port);
console.log("The resource in the URL is " + parsedUrl.resource);
console.log("The user in the URL is " + parsedUrl.user);
console.log("The pathname in the URL is " + parsedUrl.pathname);
console.log("The hash in the URL is " + parsedUrl.hash);
console.log("The search part in the URL is " + parsedUrl.search);
console.log("Full URL is " + parsedUrl.href);
运行这段代码的结果是
The protocols used in the URL are git,ssh
The port used in the URL is 30
The resource in the URL is somehost.com
The user in the URL is git
The pathname in the URL is /path/to/resource.git
The hash in the URL is anchor
The search part in the URL is key1=value1&key2=value2
Full URL is git+ssh://git@somehost.com:30/path/to/resource.git?key1=value1&key2=value2#anchor
最后,让我们看看URL规范化的结果。如果我们传递一个未规范化的URL,如stackabuse.com:3000/path/to/index.html#anchor ,作为一个URL字符串。
const url = 'stackabuse.com:3000/path/to/index.html#anchor';
const parsedUrl = parseUrl(url, true);
console.log(parsedUrl);
这样的结果是:
{
protocols: [ 'http' ],
protocol: 'http',
port: 3000,
resource: 'stackabuse.com',
user: '',
pathname: '/path/to/index.html',
hash: 'anchor',
search: '',
href: 'http://stackabuse.com:3000/path/to/index.html#anchor',
query: [Object: null prototype] {}
}
我们可以看到,解析器自动将http 作为协议,并正确填写了href 属性。缺少的部分没有被填入,因为它们一开始就没有被提供。
如果我们禁用规范化功能,同时提供一个非规范化的URL,结果就会出现偏差。
{
protocols: [],
protocol: 'file',
port: null,
resource: '',
user: '',
pathname: 'stackabuse.com:3000/path/to/index.html',
hash: 'anchor',
search: '',
href: 'stackabuse.com:3000/path/to/index.html#anchor',
query: [Object: null prototype] {}
}
**注意:**如果你把normalize 设为true ,并提供一个已经规范化的URL,其实什么都不会发生,而且会被正确解析。鉴于此--你通常会想把这个参数设置为真。
由于parsedUrl 是一个对象,它的属性可以被改变。我们可以简单地访问任何属性并改变它。
console.log(parsedUrl.port) // 3000
parsedUrl.port = 4000
console.log(parsedUrl.port) // 4000
然而,这不是我们想要的行为,也不应该这样做,因为这个模块仅仅是用来解析URLs的。你唯一应该这样改变parsedUrl 对象的时候,是你对某些属性的值有信心的时候,否则,你可能会射中自己的腿。
总结
我们已经看到parse-url ,让我们相当容易地解析URL,而不需要任何额外的处理,并使解析URL的过程极其简单和可读。
它根据需要将所有东西分割开来,并创建一个parsedUrl 对象,可以像其他对象一样被访问,也可以被改变。该模块和它们一样简单,有整齐的输出和语法,并尽可能地直接导致快速和精确的结果。