[インデックス 12649] ファイルの概要
このコミットは、Go言語のドキュメンテーションツールであるgodoc
の検索機能におけるURL生成のバグ修正に関するものです。具体的には、検索結果からソースコードへのリンクが誤った形式で生成され、//
(二重スラッシュ)が含まれてしまう問題を解決しています。
コミット
commit b4e0aeac3222e9d18837c564bba6d72a76b3dbf7
Author: Russ Cox <rsc@golang.org>
Date: Thu Mar 15 14:50:51 2012 -0400
lib/godoc: removing leading / from search links
srcLink includes the / now; adding another yields //,
which means something else entirely in URLs.
Fixes #3327.
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5823060
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b4e0aeac3222e9d18837c564bba6d72a76b3dbf7
元コミット内容
lib/godoc/search.html
ファイルにおいて、検索結果からソースコードへのリンクを生成する際に、URLのパスに余分なスラッシュ(/
)が追加されてしまう問題を修正しました。これは、srcLink
関数がすでにパスの先頭にスラッシュを含んでいるにもかかわらず、テンプレート内でさらにスラッシュを追加していたため、結果的に//
という形式になってしまうことが原因でした。URLにおいて//
は特別な意味を持つ場合があるため、これを修正することで正しいリンクが生成されるようになります。この修正はIssue #3327を解決します。
変更の背景
Go言語の公式ドキュメンテーションツールであるgodoc
は、Goのソースコードからドキュメントを生成し、Webブラウザで閲覧できるようにするものです。このツールには検索機能も含まれており、検索結果から該当するソースコードの行に直接ジャンプできるリンクが提供されています。
このコミットが行われる前は、godoc
の検索結果ページで表示されるソースコードへのリンクが正しく機能しない、または意図しない動作をする可能性がありました。具体的には、リンクのURLが//
で始まる形になってしまい、これがブラウザやWebサーバーによって異なる解釈をされることが問題でした。例えば、http://example.com//path/to/file
のようなURLは、http://path/to/file
として解釈され、ドメインが変更されてしまうといったセキュリティ上の問題や、単にリンク切れになるなどの機能的な問題を引き起こす可能性があります。
コミットメッセージにあるFixes #3327
は、この問題がGoのIssueトラッカーで報告されていたことを示しています。開発者はこの報告を受けて、URLの生成ロジックに誤りがあることを特定し、修正を行いました。
前提知識の解説
1. godoc
とは
godoc
は、Go言語のソースコードからドキュメントを自動生成し、Webブラウザで閲覧可能にするツールです。Goのパッケージ、関数、型、変数などのドキュメントを、コメントに基づいて自動的に抽出・整形します。開発者がコードとドキュメントを同時に管理できるため、ドキュメントの鮮度を保ちやすいという特徴があります。
2. URLのパスにおけるスラッシュ(/
)の役割
WebにおけるURL(Uniform Resource Locator)は、リソースの場所を一意に特定するためのものです。URLの構造は一般的に以下のようになります。
scheme://host:port/path?query#fragment
この中で、path
部分はリソースの階層的な場所を示します。スラッシュ(/
)はパスの区切り文字として機能します。
- 単一スラッシュ(
/
): パスの区切りを示します。また、パスの先頭にある場合は、ルートディレクトリからの絶対パスを示します。例:/users/profile
- 二重スラッシュ(
//
): URLのスキーム(http:
やhttps:
)の直後に続く場合は、ホスト名の開始を示します。例:http://example.com
。しかし、パスの途中に現れる場合、その解釈はWebサーバーやブラウザの実装に依存します。多くの場合、単一のスラッシュとして扱われますが、一部のシステムでは特別な意味を持つか、エラーを引き起こす可能性があります。特に、http://host//path
のような形式は、host
の後に続く//
が、新しいホスト名(この場合は空のホスト名)の開始と解釈され、その後のpath
がそのホスト名に対する絶対パスとして扱われるという、意図しない挙動を引き起こすことがあります。
3. Goのhtml/template
パッケージ
Go言語の標準ライブラリには、HTMLテンプレートを扱うためのhtml/template
パッケージがあります。このパッケージは、Webアプリケーションで動的にHTMLコンテンツを生成する際に使用されます。セキュリティ上の理由から、このパッケージは自動的にHTMLエスケープ処理を行います。これにより、クロスサイトスクリプティング(XSS)などの脆弱性を防ぐことができます。
テンプレート内で変数を埋め込む際、{{.Variable}}
のような構文を使用します。また、関数を呼び出すこともでき、{{funcName .Variable}}
のように記述します。このコミットでは、srcLink
という関数が使用されており、これがソースコードへのリンクパスを生成していると推測されます。
技術的詳細
このコミットの技術的な核心は、URLのパス生成における絶対パスと相対パスの扱い、そしてhtml/template
の挙動の理解にあります。
godoc
のsearch.html
テンプレートでは、検索結果の各項目に対してソースコードへのリンクを生成しています。このリンクのURLは、srcLink
というテンプレート関数(または変数)によって生成されるパスと、テンプレート内で明示的に追加されるスラッシュを組み合わせて作られていました。
元のコードでは、以下のような形式でリンクが生成されていました。
<a href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">...</a>
ここで、$src_html
はsrcLink .File.Path | html
の結果です。コミットメッセージによると、srcLink
はすでにパスの先頭にスラッシュ(/
)を含んでいました。例えば、srcLink
が/src/pkg/foo/bar.go
のような文字列を返していたとします。
この場合、テンプレート内でさらに/
を追加すると、結果的にURLは/
+ /src/pkg/foo/bar.go
となり、//src/pkg/foo/bar.go
という形式になってしまいます。
URLの仕様において、//
がパスの途中に現れる場合、その解釈は曖昧になることがあります。特に、http://host//path
のような形式は、一部のブラウザやサーバーでhttp://path
として解釈される可能性があり、これはセキュリティ上の問題(オープンリダイレクトなど)や、単にリソースが見つからないという機能的な問題を引き起こします。
このコミットでは、srcLink
がすでに先頭スラッシュを含んでいるという事実に基づき、テンプレート内で余分なスラッシュを追加するのをやめました。
修正後のコードは以下のようになります。
<a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">...</a>
これにより、srcLink
が返すパス(例: /src/pkg/foo/bar.go
)が直接href
属性に設定され、正しい絶対パスのURLが生成されるようになります。
この修正は、HTMLテンプレートにおけるパスの結合ロジックの正確性を保証し、URLの解釈に関する潜在的な問題を回避するために重要です。
コアとなるコードの変更箇所
変更はlib/godoc/search.html
ファイルのみで行われています。
--- a/lib/godoc/search.html
+++ b/lib/godoc/search.html
@@ -38,7 +38,7 @@
{{$src_html := srcLink .File.Path | html}}
{{range .Groups}}
{{range .}}
- <a href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{$src_html}}:{{infoLine .}}</a>
+ <a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{$src_html}}:{{infoLine .}}</a>
{{infoSnippet_html .}}
{{end}}
{{end}}
@@ -52,7 +52,7 @@
<h3 id=\"Local_{{$pkg_html}}\">package <a href=\"/{{$pkg_html}}\">{{html .Pak.Name}}</a></h3>
{{range .Files}}
{{$src_html := srcLink .File.Path | html}}
- <a href=\"/{{$src_html}}?h={{$query_url}}\">{{$src_html}}</a>
+ <a href="{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>
<table class=\"layout\">\
{{range .Groups}}
<tr>
@@ -61,7 +61,7 @@
<td align=\"left\" width=\"4\"></td>
<td>
{{range .}}
- <a href=\"/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}\">{{infoLine .}}</a>
+ <a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}\">{{infoLine .}}</a>
{{end}}\
</td>
</tr>
@@ -86,14 +86,14 @@
{{$src_html := srcLink .Filename | html}}
<tr>
<td align=\"left\" valign=\"top\">\
- <a href=\"/{{$src_html}}?h={{$query_url}}\">{{$src_html}}</a>:\
+ <a href="{{$src_html}}?h={{$query_url}}\">{{$src_html}}</a>:\
</td>
<td align=\"left\" width=\"4\"></td>
<th align=\"left\" valign=\"top\">{{len .Lines}}</th>
<td align=\"left\" width=\"4\"></td>
<td align=\"left\">\
{{range .Lines}}\
- <a href=\"/{{$src_html}}?h={{$query_url}}#L{{html .}}\">{{html .}}</a>
+ <a href="{{$src_html}}?h={{$query_url}}#L{{html .}}\">{{html .}}</a>
{{end}}\
{{if not $.Complete}}\
...\
コアとなるコードの解説
変更はすべて<a>
タグのhref
属性内で行われています。具体的には、href
属性の値の先頭から余分なスラッシュ(/
)が削除されています。
元のコード:
href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}"
修正後のコード:
href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}"
この変更は、$src_html
変数がすでにパスの先頭にスラッシュを含んでいるという前提に基づいています。$src_html
はsrcLink .File.Path | html
またはsrcLink .Filename | html
の結果であり、srcLink
関数が絶対パスを返すように設計されているため、テンプレート内でさらにスラッシュを追加する必要がありませんでした。
この修正により、生成されるURLは//
を含まなくなり、godoc
の検索結果ページからソースコードへのリンクが正しく機能するようになります。
関連リンク
- Go Issue #3327: https://github.com/golang/go/issues/3327 (このコミットが修正したIssue)
- Go Code Review: https://golang.org/cl/5823060 (このコミットのコードレビューページ)
参考にした情報源リンク
- Go言語公式ドキュメント: https://go.dev/
- HTML
<a>
タグのhref
属性に関するMDN Web Docs: https://developer.mozilla.org/ja/docs/Web/HTML/Element/a - URLの構文に関するRFC 3986: https://datatracker.ietf.org/doc/html/rfc3986 (特にセクション 3.3 Path)
- Go
html/template
パッケージのドキュメント: https://pkg.go.dev/html/template - Go
godoc
コマンドのドキュメント: https://pkg.go.dev/cmd/godoc