PuerkitoBio/purell

GitHub: PuerkitoBio/purell

Purell 是一个基于 Go 的轻量级 URL 规范化库,通过灵活的标志位组合将 URL 转换为统一的纯净格式。

Stars: 485 | Forks: 61

# Purell Purell 是一个小巧的 Go 库,用于规范化 URL。它返回一个纯净的 URL。Pure-ell(纯净)。就像净化器一样。是的,我知道…… 基于 [维基百科文章][wiki] 和 [RFC 3986 文档][rfc]。 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/PuerkitoBio/purell/actions/workflows/ci.yml) ## 安装 `go get github.com/PuerkitoBio/purell` ## 更新日志 * **2026-05-17 (v1.2.2)** :修复了由于 CVE-2025-47912 引入的更严格的 IPv6 主机验证而导致的 Go 1.24.8+ 测试失败问题(感谢 @syedazeez337),并为 GitHub Actions 引入了 zizmor 检查。 * **2023-10-22 (v1.2.1)** :修复了主机名部分之间多余点的 `FlagRemoveUnnecessaryHostDots` 问题(感谢 @michael-peterson-cisco),并升级了依赖项。 * **2022-08-17 (v1.2.0)** :迁移至 Go modules,将 CI 移至 GitHub Actions,内联了来自 urlesc 的 URL 转义支持,并在 Go 1.19 上运行 CI。 * **v1.1.1** :修复了由于 Go1.12 更改导致的测试失败问题(感谢 @ianlancetaylor)。 * **2016-11-14 (v1.1.0)** :IDN:符合 RFC 5895:折叠字符宽度(感谢 @beeker1121)。 * **2016-07-27 (v1.0.0)** :将 IDN 规范化为 ASCII(感谢 @zenovich)。 * **2015-02-08** :添加了对相对路径问题的修复([PR #5][pr5]),并添加了对保留字符不必要编码的修复([参见 issue #7][iss7])。 * **v0.2.0** :添加了基准测试,尝试支持 IDN。 * **v0.1.0** :初始版本。 ## 示例 摘自 `example_test.go`(请注意,在你的代码中,你需要导入 "github.com/PuerkitoBio/purell",并且在引用其方法和常量时需要加上 "purell." 前缀): ``` package purell import ( "fmt" "net/url" ) func ExampleNormalizeURLString() { if normalized, err := NormalizeURLString("hTTp://someWEBsite.com:80/Amazing%3f/url/", FlagLowercaseScheme|FlagLowercaseHost|FlagUppercaseEscapes); err != nil { panic(err) } else { fmt.Print(normalized) } // Output: http://somewebsite.com:80/Amazing%3F/url/ } func ExampleMustNormalizeURLString() { normalized := MustNormalizeURLString("hTTpS://someWEBsite.com:443/Amazing%fa/url/", FlagsUnsafeGreedy) fmt.Print(normalized) // Output: http://somewebsite.com/Amazing%FA/url } func ExampleNormalizeURL() { if u, err := url.Parse("Http://SomeUrl.com:8080/a/b/.././c///g?c=3&a=1&b=9&c=0#target"); err != nil { panic(err) } else { normalized := NormalizeURL(u, FlagsUsuallySafeGreedy|FlagRemoveDuplicateSlashes|FlagRemoveFragment) fmt.Print(normalized) } // Output: http://someurl.com:8080/a/c/g?c=3&a=1&b=9&c=0 } ``` ## API 正如上方示例所示,purell 提供了三个方法:`NormalizeURLString(string, NormalizationFlags) (string, error)`、`MustNormalizeURLString(string, NormalizationFlags) (string)` 和 `NormalizeURL(*url.URL, NormalizationFlags) (string)`。它们都会根据指定的标志位对提供的 URL 进行规范化。以下是可用的标志位: ``` const ( // Safe normalizations FlagLowercaseScheme NormalizationFlags = 1 << iota // HTTP://host -> http://host, applied by default in Go1.1 FlagLowercaseHost // http://HOST -> http://host FlagUppercaseEscapes // http://host/t%ef -> http://host/t%EF FlagDecodeUnnecessaryEscapes // http://host/t%41 -> http://host/tA FlagEncodeNecessaryEscapes // http://host/!"#$ -> http://host/%21%22#$ FlagRemoveDefaultPort // http://host:80 -> http://host FlagRemoveEmptyQuerySeparator // http://host/path? -> http://host/path // Usually safe normalizations FlagRemoveTrailingSlash // http://host/path/ -> http://host/path FlagAddTrailingSlash // http://host/path -> http://host/path/ (should choose only one of these add/remove trailing slash flags) FlagRemoveDotSegments // http://host/path/./a/b/../c -> http://host/path/a/c // Unsafe normalizations FlagRemoveDirectoryIndex // http://host/path/index.html -> http://host/path/ FlagRemoveFragment // http://host/path#fragment -> http://host/path FlagForceHTTP // https://host -> http://host FlagRemoveDuplicateSlashes // http://host/path//a///b -> http://host/path/a/b FlagRemoveWWW // http://www.host/ -> http://host/ FlagAddWWW // http://host/ -> http://www.host/ (should choose only one of these add/remove WWW flags) FlagSortQuery // http://host/path?c=3&b=2&a=1&b=1 -> http://host/path?a=1&b=1&b=2&c=3 // Normalizations not in the wikipedia article, required to cover tests cases // submitted by jehiah FlagDecodeDWORDHost // http://1113982867 -> http://66.102.7.147 FlagDecodeOctalHost // http://0102.0146.07.0223 -> http://66.102.7.147 FlagDecodeHexHost // http://0x42660793 -> http://66.102.7.147 FlagRemoveUnnecessaryHostDots // http://.host../path -> http://host/path FlagRemoveEmptyPortSeparator // http://host:/path -> http://host/path // Convenience set of safe normalizations FlagsSafe NormalizationFlags = FlagLowercaseHost | FlagLowercaseScheme | FlagUppercaseEscapes | FlagDecodeUnnecessaryEscapes | FlagEncodeNecessaryEscapes | FlagRemoveDefaultPort | FlagRemoveEmptyQuerySeparator // For convenience sets, "greedy" uses the "remove trailing slash" and "remove www. prefix" flags, // while "non-greedy" uses the "add (or keep) the trailing slash" and "add www. prefix". // Convenience set of usually safe normalizations (includes FlagsSafe) FlagsUsuallySafeGreedy NormalizationFlags = FlagsSafe | FlagRemoveTrailingSlash | FlagRemoveDotSegments FlagsUsuallySafeNonGreedy NormalizationFlags = FlagsSafe | FlagAddTrailingSlash | FlagRemoveDotSegments // Convenience set of unsafe normalizations (includes FlagsUsuallySafe) FlagsUnsafeGreedy NormalizationFlags = FlagsUsuallySafeGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagRemoveWWW | FlagSortQuery FlagsUnsafeNonGreedy NormalizationFlags = FlagsUsuallySafeNonGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagAddWWW | FlagSortQuery // Convenience set of all available flags FlagsAllGreedy = FlagsUnsafeGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator FlagsAllNonGreedy = FlagsUnsafeNonGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator ) ``` 为了方便起见,提供了 `FlagsSafe`、`FlagsUsuallySafe[Greedy|NonGreedy]`、`FlagsUnsafe[Greedy|NonGreedy]` 和 `FlagsAll[Greedy|NonGreedy]` 标志集,用于在 [维基百科的 URL 规范化页面][wiki] 上进行类似的分组规范化。如果需要,你可以从这些集合中添加(使用按位或 `|` 运算符)或移除(使用按位与非 `&^` 运算符)单个标志,以构建你自己的自定义集合。 [完整的 godoc 参考文档可在 gopkgdoc 上找到][godoc]。 需要注意的一些事项: * `FlagDecodeUnnecessaryEscapes`、`FlagEncodeNecessaryEscapes`、`FlagUppercaseEscapes` 和 `FlagRemoveEmptyQuerySeparator` 总是会被隐式设置,因为在内部,URL 字符串会被解析为 URL 对象,该对象会自动解码不必要的转义,将必要的转义大写并编码,并移除空的查询分隔符(位于 URL 末尾不必要的 `?`)。因此,这个操作**必然**会执行。出于这个原因,`FlagRemoveEmptyQuerySeparator`(以及其他三个)已被包含在 `FlagsSafe` 便捷集合中,而不是维基百科所放置的 `FlagsUnsafe` 中。 * `FlagDecodeUnnecessaryEscapes` 会解码以下转义字符(*从 -> 至*): - %24 -> $ - %26 -> & - %2B-%3B -> +,-./0123456789:; - %3D -> = - %40-%5A -> @ABCDEFGHIJKLMNOPQRSTUVWXYZ - %5F -> _ - %61-%7A -> abcdefghijklmnopqrstuvwxyz - %7E -> ~ * 当使用 `NormalizeURL` 函数时(传入一个 URL 对象),该源 URL 对象会被修改(也就是说,调用之后,URL 对象将被修改以反映规范化后的结果)。 * *将 IP 替换为域名*的规范化(`http://208.77.188.166/ → http://www.example.com/`)在不发起网络请求的情况下,对于库来说显然是无法实现的。这在 purell 中未实现。 * *移除未使用的查询字符串参数*和*移除默认查询参数*也未实现,因为这是一种非常特定于具体场景的规范化,而且使用 URL 对象来执行此操作非常简单。 ### 安全 与 通常安全 与 不安全 的对比 Purell 允许你控制在规范化 URL 时所承担的风险级别。你可以激进地进行规范化,也可以采取完全安全的策略,或者介于两者之间。 考虑以下 URL: `HTTPS://www.RooT.com/toto/t%45%1f///a/./b/../c/?z=3&w=2&a=4&w=1#invalid` 使用 `FlagsSafe` 进行规范化会得到: `https://www.root.com/toto/tE%1F///a/./b/../c/?z=3&w=2&a=4&w=1#invalid` 使用 `FlagsUsuallySafeGreedy` 会得到: `https://www.root.com/toto/tE%1F///a/c?z=3&w=2&a=4&w=1#invalid` 而使用 `FlagsUnsafeGreedy` 会得到: `http://root.com/toto/tE%1F/a/c?a=4&w=1&w=2&z=3` ## 待办事项 * 添加一个类/默认实例以允许指定自定义的目录索引名称?目前,移除目录索引会移除 `(^|/)((?:default|index)\.\w{1,4})$`。 ## 致谢 / 贡献 请参阅 。 ## 许可证 采用 [BSD 3-Clause 许可证][bsd]。
标签:EVTX分析, Go, Ruby工具, Syscall, URL规范化, URL解析, Web开发, 开发工具库, 日志审计