2

在浏览器输入网址,Enter之后发生了什么? - 博客猿马甲哥

 1 week ago
source link: https://www.cnblogs.com/JulianHuang/p/18154545
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在浏览器输入网址,Enter之后发生了什么?

587720-20240424103236279-1304039254.webp

很多八股文会给出:

  1. DNS Resolution
  2. Establishing a Connection
  3. Sending an Http Request
  4. Receiving the HTTP Response
  5. Rendering the Web Page

但今天我斗胆插入第0.9步URL Parsing

URL( uniform resource locator)由四部分组成: scheme、domain、path、resource

ff6099130f184431842b9977996d21bc~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=908&h=327&s=103745&e=png&b=f8f7f7

URL Parsing做了2个事情:

  • prase url:只有解析分离出domain,还有后续的第1步: DNS resolution
  • url_encode

本文我主要想聊一聊url_encode

  1. 为什么会有url_encode?
  2. javascript encodeURI() vs encodeURIComponent()
  3. 我为什么会想到这个问题?
  4. 常见的httpclient默认有做url_encode吗?

在浏览器插入https://www.baidu.com/s?wd=博客园马甲哥,Enter之前童鞋们可尝试拷贝地址栏, 粘贴到任意位置, 内容是:https://www.baidu.com/s?wd=%E5%8D%9A%E5%AE%A2%E5%9B%AD%E9%A9%AC%E7%94%B2%E5%93%A5, 这就是浏览器自动url_encode的结果, 浏览器会拿这个网址去做 dns、request行为。

1. 为什么会有url_encode?

url_encode 又叫百分号编码,为什么要有url_encode,看知乎。

总结下来:uri地址最初要求是以可显示、可写的 ascii 字符集, 非英文字符和其他特殊字符需要被编码。

默认按照UTF-8转化为字节流,每个字节按16进制表示,并添加%组成一个percent编码。

UTF-8 到底是什么意思?

例如:汉字 “你好”

  • UTF-8字节流打印为:-28 -67 -96 -27 -91 -67
  • 对应的16进制表示为:E4 BD A0 E5 A5 BD
  • URLEncode编译后为:%E4%BD%A0%E5%A5%BD

当然服务端会对应的url_decode函数,编码/解码的次数需要对应。

2. js 中的encodeURI() vs encodeURIComponent()

encodeURI是js 中内置的全局函数,用于url_encode,不会对以下特殊字符编码,这也是为了确保url中原生字符的正确表达:
A–Z a–z 0–9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , #

const uri = 'https://mozilla.org/?x=шеллы';
const encoded = encodeURI(uri);
console.log(encoded);
// Expected output: "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"

encodeURIComponent 也是全局函数,但他的用途是对字符串做完整的url_encode, 这个函数会对上面排除的字符做编码,这个函数一般用于已知是特殊字符需要做url编码。

// Encodes characters such as ?,=,/,&,:
console.log(`?x=${encodeURIComponent('test?')}`);
// Expected output: "?x=test%3F"

3.我为什么会关注这个问题?

一般web框架会为我们自动解码,所以我们在直接处理http请求时可以忽略该问题。

但是在自行使用 httpclient反代时就要注意这个问题。

7d0196044974442391f32aae25f24780~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1688&h=390&s=76409&e=png&b=fbf7f7

nginx内置变量并提供了自定义变量的能力

  • $request_uri
    full original request URI (with arguments)
  • $uri
    current URI in request, normalized,
    The value of $uri may change during request processing, e.g. when doing internal redirects, or when using index files.

我在使用lua-resty-http客户端做反向代理请求时遇到了这个问题, 一开始lua_resty_http 将 $uri(解码值)送到应用,不符合应用的预期, 应恢复成原始编码uri

4. 常见的httpclient是否指出自动url_encode?

.NET、go、lua的HttpClient(包括curl)都不会自动对 URL 进行编码。 如果你的 URL 包含特殊字符或需要编码的字符,你需要自己手动进行 URL 编码。

  • [C#] System.Net.WebUtility.UrlEncode
  • [golang] url.QueryEscape(rawURL)
  • [lua] ngx.escape_uri(str, 0)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK