Skip to content

Commit 6f8b6c5

Browse files
committed
feat: add new post
1 parent 35b24ef commit 6f8b6c5

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

content/posts/url-urlsearchparams.md

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
+++
2+
title = "مشکلات URL و URLSearchParams"
3+
author = "حمیدرضا مهدوی پناه"
4+
tags = ["javascript", "typescript", "node.js"]
5+
keywords = ["js", "جاوااسکریپت", "URLSearchParams", "URL", "node.js", "url", "typescript"]
6+
year = "۱۴۰۳"
7+
month = "۹"
8+
day = "۲"
9+
date = "2024-11-22"
10+
draft = false
11+
+++
12+
13+
بررسی تفاوت‌های ریزی که حین کار با URLها باعث به وجود آمدن باگ‌های غیرمنتظره می‌شود.
14+
15+
<!--more-->
16+
17+
## همه چیز از یک باگ شروع شد
18+
19+
کار با URL‌ها در JavaScript و Node.js باید ساده باشد، اما یک باگ اخیر در پروژه ما، من را به دنیایی از جزئیات پیچیده در [API‌های `URL` و `URLSearchParams`](https://nodejs.org/api/url.html) برد. در این پست، به بررسی این جزئیات و مشکلات احتمالی آن‌ها در کد و نحوه اجتناب از آن‌ها خواهیم پرداخت.
20+
21+
---
22+
23+
## مشکل: مدیریت URL با Axios
24+
25+
ما این مشکل را هنگام تولید URL‌ها و اضافه کردن امضا‌های هش به آن‌ها پیدا کردیم. پارامترهای کوئری به طور یک‌پارچه percent-encode نمی‌شدند که منجر به رفتار غیرمنتظره و امضا‌های هش اشتباه می‌شد.
26+
27+
واضح شد که تعامل بین اشیای `URL` و `URLSearchParams` نیاز به دقت بیشتری دارد.
28+
29+
---
30+
31+
### مشکل شماره 1: تفاوت بین `URL.search` و `()URLSearchParams.toString`
32+
33+
اولین شگفتی تفاوت بین `URL.search` و `()URLSearchParams.toString` بود.
34+
35+
هنگام استفاده از `searchParams.` برای تغییر `URL`، دقت کنید، زیرا طبق [مشخصات WHATWG](https://url.spec.whatwg.org/) ، شیء `URLSearchParams` از قوانین متفاوتی برای تعیین اینکه کدام کاراکترها باید percent-encode شوند استفاده می‌کند. به عنوان مثال، شیء `URL` کاراکتر تیلد ASCII (`~`) را percent-encode نمی‌کند، در حالی که `URLSearchParams` همیشه آن را encode می‌کند.
36+
37+
```typescript
38+
// Example 1
39+
const url = new URL("https://example.com?param=foo bar")
40+
console.log(url.search) // prints param=foo%20bar
41+
console.log(url.searchParams.toString()) // prints ?param=foo+bar
42+
43+
// Example 2
44+
const myURL = new URL("https://example.org/abc?foo=~bar")
45+
console.log(myURL.search) // prints ?foo=~bar
46+
// Modify the URL via searchParams...
47+
myURL.searchParams.sort()
48+
console.log(myURL.search) // prints ?foo=%7Ebar
49+
```
50+
51+
در پروژه ما، لازم بود به طور صریح `()url.search = url.searchParams.toString` را دوباره اختصاص دهیم تا اطمینان حاصل شود که رشته کوئری به طور یکنواخت encode شده است.
52+
53+
---
54+
55+
### مشکل شماره 2: چالش علامت بعلاوه
56+
57+
یکی دیگر از نکات ظریف این است که چگونه `URLSearchParams` با کاراکترهای `+` برخورد می‌کند. به طور پیش‌فرض، `URLSearchParams` کاراکتر `+` را به عنوان فضای خالی تفسیر می‌کند که ممکن است هنگام encode داده‌های باینری یا رشته‌های Base64 منجر به خرابی داده‌ها شود.
58+
59+
```typescript
60+
const params = new URLSearchParams("bin=E+AXQB+A")
61+
console.log(params.get("bin")) // "E AXQB A"
62+
```
63+
64+
یک راه حل این است که قبل از افزودن مقادیر به `URLSearchParams` از `encodeURIComponent` استفاده کنید:
65+
66+
```typescript
67+
params.append("bin", encodeURIComponent("E+AXQB+A"))
68+
```
69+
70+
جزئیات بیشتر در [مستندات MDN](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#preserving_plus_signs) موجود است.
71+
72+
---
73+
74+
### مشکل شماره 3: `URLSearchParams.get` در مقابل `()URLSearchParams.toString`
75+
76+
یکی دیگر از جزئیات ظریف زمانی به وجود می‌آید که خروجی‌های `URLSearchParams.get` و `URLSearchParams.toString` را مقایسه می‌کنید. به عنوان مثال:
77+
78+
```typescript
79+
const params = new URLSearchParams("?key=value&key=other")
80+
console.log(params.get("key")) // "value" (اولین مورد)
81+
console.log(params.toString()) // "key=value&key=other" (همه موارد سریالایز شده)
82+
```
83+
84+
در سناریوهای چند مقداری، `get` فقط اولین مقدار را برمی‌گرداند، در حالی که `toString` همه را سریالایز می‌کند.
85+
86+
---
87+
88+
## راه‌حل در کد ما
89+
90+
در پروژه ما، مشکل را با اختصاص صریح `search` حل کردیم:
91+
92+
```typescript
93+
url.search = url.searchParams.toString()
94+
url.searchParams.set(
95+
"hash",
96+
cryptography.createSha256HmacBase64UrlSafe(url.href, SECRET_KEY ?? "")
97+
)
98+
```
99+
100+
این اطمینان حاصل کرد که تمام پارامترهای کوئری قبل از اضافه کردن مقدار `hash` به درستی encode شده بودند.
101+
102+
---
103+
104+
## ماژول `querystring` در Node.js
105+
106+
رابط کاربری WHATWG `URLSearchParams` و [ماژول `querystring`](https://nodejs.org/api/querystring.html) هدف مشابهی دارند، اما هدف ماژول `querystring` عمومی‌تر است، زیرا امکان سفارشی‌سازی کاراکترهای جداکننده (`&` و `=`) را فراهم می‌کند. از سوی دیگر، API `URLSearchParams` به طور خاص برای رشته‌های کوئری URL طراحی شده است.
107+
108+
ماژول `querystring` از `URLSearchParams` کارآمدتر است اما یک API استاندارد نیست. از `URLSearchParams` زمانی استفاده کنید که عملکرد بحرانی نیست یا وقتی سازگاری با کد مرورگر مطلوب است.
109+
110+
هنگام استفاده از `URLSearchParams` برخلاف ماژول `querystring`، کلیدهای تکراری به صورت آرایه مجاز نیستند. آرایه‌ها با استفاده از `()array.toString` سریالایز می‌شوند که به سادگی همه عناصر آرایه را با کاما جدا می‌کند.
111+
112+
```typescript
113+
const params = new URLSearchParams({
114+
user: "abc",
115+
query: ["first", "second"],
116+
})
117+
console.log(params.getAll("query"))
118+
// Prints [ 'first,second' ]
119+
console.log(params.toString())
120+
// Prints 'user=abc&query=first%2Csecond'
121+
```
122+
123+
با ماژول `querystring`، رشته کوئری `'foo=bar&abc=xyz&abc=123'` به این صورت پارس می‌شود:
124+
125+
```typescript
126+
{
127+
"foo": "bar",
128+
"abc": ["xyz", "123"]
129+
}
130+
```
131+
132+
---
133+
134+
## نکات کلیدی
135+
136+
1. هنگام استفاده از `URLSearchParams` به نحوه مدیریت کاراکترهای خاص (مانند `~`) و فضاهای خالی توجه کنید. در صورت نیاز از `encodeURIComponent` استفاده کنید.
137+
138+
2. تفاوت بین `URL.search`، `URLSearchParams.get` و `URLSearchParams.toString` را برای جلوگیری از رفتار غیرمنتظره درک کنید.
139+
140+
3. در Node.js از ماژول `querystring` استفاده کنید اگر می‌خواهید پارامترهای کوئری تکراری را به عنوان یک آرایه پارس کنید.
141+
142+
---
143+
144+
منبع:
145+
[Pitfalls of URL and URLSearchParams in JavaScript](https://hamidreza.tech/pitfalls-of-url-and-urlsearchparams-in-nodejs)
146+
از وبلاگ
147+
Software Alchemist

0 commit comments

Comments
 (0)