aio-libs / aio-libs/yarl

URL.join() decodes percent-encoded characters in the base path (e.g. %2F becomes /)

未關閉 適合新手
#1,774 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
Python
星號
1.5k
分支
215
平均合併
1 天 2 分鐘
30 天內合併 PR
13

描述

### Description

`URL.join()` decodes percent-encoded characters in the base URL's path when merging a relative reference (RFC 3986 §5.3, the branch used when the base path does not end with `/`). The merge is built from `self.parts`, which are already percent-decoded, so an encoded delimiter like `%2F` is turned into a real `/` and the path structure is corrupted.

### Reproduction

```python
from yarl import URL

print(URL("http://x/a%2Fb/c").join(URL("d"))) # http://x/a/b/d
print(URL("http://x/a%20b/c").join(URL("d"))) # http://x/a b/d
```

### Expected vs actual

| | result |
|---|---|
| expected | `http://x/a%2Fb/d` (the `a%2Fb` segment is preserved) |
| actual | `http://x/a/b/d` (`%2F` decoded into a separator -> the single segment splits into two) |

`%20` is likewise decoded into a literal space.

### Root cause

The RFC-3986 merge branch in `URL.join` constructs the merged path from `self.parts[:-1]`. `parts` runs the segments through `UNQUOTER` (decoded), so feeding them back into a path mixes decoded text with the still-encoded relative path. The raw/encoded segments (`raw_parts`) should be used for the merge so the original encoding round-trips.

(Distinct from #896, which is RFC-correct last-segment replacement; this is specifically the loss of percent-encoding.)

貢獻指南

開啟貢獻指南

研究方向

Start in URL.join, specifically the RFC 3986 merge branch used when the base path lacks a trailing slash, and compare how self.parts and raw_parts represent encoded segments. Add regression coverage for the supplied %2F and %20 examples; done means the encoded path is preserved in the joined URL.

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
backend
Issue 類型
缺陷
難度
2/5
預估耗時
1-3 小時
活躍度
冷清
描述清晰度
描述清楚
新手友好度
78/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。