Percent encoding در URL باید با مرزِ همان جزء تفسیر شود. علامتِ+ در قراردادِ queryِفرمی میتواند فاصله باشد، اما در هر مسیر یا هر URL الزاماً این معنی را ندارد. تمرین این صفحه هفت مقدارِ اصیل را جدا به path segment و query value تبدیل میکند و سپس مقدارِ اولیه را دقیقاً بازمیسازد. هیچ نشانی باز یا درخواستِ شبکهای ارسال نمیشود.
اول اجزا را جدا بسازیم
همهٔ نشانیهای تمرین روی دامنهٔ نمونهٔ example.test ساخته میشوند. ساختارِ ثابت، /items/ بهاضافهٔ یک segment و query با کلیدِq است. فقط مقدارِ خامِ هر خانه تغییر میکند: فارسی، a b، a+b، a/b، a&b، رشتهٔ%2F و رشتهٔ خالی. اینها دادهٔ مشتری یا مقصدِ واقعیِ محصول نیستند.
برای segment از quote با safe='' و UTF-8ِstrict استفاده میشود؛ پس slashِداخلِ مقدار نیز encode میشود. برای query از urlencode با قراردادِ پیشفرضِ فرم و در بازگشت از parse_qs با keep_blank_values=True استفاده میکنیم. نگهداشتنِ خانهٔ خالی صریح است؛ نبودِ داده را با حذفِ بیاعلانِ کلید پنهان نمیکنیم.
فاصله و plus اصلی متفاوتاند
برای مقدارِ a b، قسمتِ مسیر a%20b و query برابرِq=a+b میشود. برای مقدارِ a+b، هر دو جایگاه plus اصلی را به%2B تبدیل میکنند. در آزمونِ جدا، parse_qs('q=a+b') مقدارِa b و parse_qs('q=a%2Bb') مقدارِa+b میدهد. موفقیتِ این دو parse با یکسانبودنِ دادهٔ اولیه یکی نیست.
| مقدارِ اصلی | segmentِ ساختهشده | queryِ فرمی |
|---|---|---|
| a b | a%20b | q=a+b |
| a+b | a%2Bb | q=a%2Bb |
| a/b | a%2Fb | q=a%2Fb |
| a&b | a%26b | q=a%26b |
پس استفاده از unquote_plus برای هر بخشِ مسیر، بدونِ قرارداد، میتواند داده را عوض کند. یک encoder و decoder باید برای همان نوعِ جزء و همان convention انتخاب شوند؛ شباهتِ ظاهرِ%xx برای یکسانبودنِ همهٔ قواعد کافی نیست.
split پیش از decode
ابتدا urlsplit اجرا میشود و path و query جدا میمانند. segment از مرزِ ثابتِ /items/ استخراج و فقط یک بار decode میشود. کد کنترل میکند pathِencoded همچنان همان تعدادِ قطعهٔ ساختاری را دارد؛ slashِداخلِ a/b قبل از decode به جداکنندهٔ مسیر تبدیل نشده است.
پس از decode، مقدارِ بازسازیشده با رشتهٔ خامِ اولیه برابر مقایسه میشود. query نیز باید دقیقاً یک کلیدِq با همان مقدار داشته باشد؛ ampersandِدرونِ داده نباید کلیدِ جدید بسازد. این انتظار از مقدارهای نویسنده میآید، نه از اینکه خروجیِ یک parser دوباره به خودش داده شود و صرفاً خطا نکند.
چرا decode دوباره میتواند مرز را عوض کند؟
رشتهٔ اصلیِ%2F خودش شاملِ یک علامتِpercent و دو حرف/رقم است؛ برای حمل در segment به%252F تبدیل میشود. یک بار decode، مقدارِاصلیِ%2F را میدهد. decode دوم آن را به slash تبدیل میکند و دیگر همان رشتهٔ منبع نیست. کد هر دو نتیجه را جدا ثبت میکند.
این ضدنمونه توصیهٔ decodeِدوباره نیست و رفتارِ عمومیِ route در همهٔ سرورها را هم پیشبینی نمیکند. RFC3986 بر جداکردنِ اجزای معنادار پیش از decode و پرهیز از encode/decodeِتکراریِ همان رشته تأکید میکند. قواعدِ برنامهٔ دریافتکننده باید از ابتدا معلوم باشند؛ تغییرِ حدسی در میانهٔ راه راهحلِ قابلِاعتماد نیست.
کل URL را quote_plus نکنیم
در مسیرِ نادرستِ آزمایشی، quote_plus روی کلِ URL اعمال میشود. colon، slashها و علامتِquery هم encode میشوند و urlsplitِنتیجه دیگر scheme پیدا نمیکند. این تفاوت واقعاً اجرا میشود تا روشن باشد encodeکردنِ «مقدارِ یک خانه» با encodeکردنِ «کل ساختارِ آدرس» یک کار نیست.
آدرسِ ظاهراً encodeشده بهتنهایی مقصدِ امن یا مجاز نیست. مستند urllib.parse نیز parser را validatorِکامل نمیداند. این تمرین هیچ DNS، redirect، میزبانِ داخلی، احرازِ هویت یا دفاعِ SSRF را آزمایش نمیکند. دربارهٔ بازشدنِ مقصد، مجوزِ دسترسی و پوششِ محتوایِ آن باید جدا تصمیم گرفت.
نتیجهٔ واقعی و ادامهٔ کار
هر هفت مقدار، از raw به encoded component و سپس مقدارِ بازگشتی، برابر شدهاند؛ فارسی با UTF-8، خانهٔ خالی با حفظِq و علامتها با مرزِ روشن سنجیده میشوند. نسخهٔ اجرا Python۳٫۱۲٫۱۴ و همهٔ کار روی رشتههای حافظهای است. این یک فرمِ آمادهٔ تبدیل در سایت یا سامانهٔ ارسالِ درخواست نیست.
حلِ نشانی و بررسیِ ارجاع مقصد و شاهدِ محتوا را دنبال میکند؛ نشانی در متنِ صوتی نیز raw، display و spoken را جدا نگه میدارد. برای ادامه در مبانی هوش مصنوعی، قراردادِ سازنده و گیرندهٔ هر جزء را ثبت کنید؛ این صفحه وجودِ URL encoder خاصی در محصولِ اپرا یا درستخواندنِ صوتیِ نشانی را اعلام نمیکند.
فایل تمرین و منبع
کد کامل تمرینِ محلی و کنترلهای آن · نمونههای اصیل و نتیجهٔ اجرای واقعیِ همین کد
- RFC3986،ژانویه۲۰۰۵؛۲٫۲تا۲٫۴،مرزِجزءوداده،percentوdecodeتکراری؛بخشهای مرتبط
- مستندPython۳٫۱۲،urlsplit/parse،quote/quote_plus/unquoteوurlencode/parse_qsوحدودvalidation؛بخشهای مرتبط
منابع در 2026-11-04 خوانده شدند؛ این تاریخ، تاریخ انتشار منبع نیست. مثالها و فایلهای این راهنما آموزشی و ساختهٔ تحریریهاند.