Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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の挙動の理解にあります。

godocsearch.htmlテンプレートでは、検索結果の各項目に対してソースコードへのリンクを生成しています。このリンクのURLは、srcLinkというテンプレート関数(または変数)によって生成されるパスと、テンプレート内で明示的に追加されるスラッシュを組み合わせて作られていました。

元のコードでは、以下のような形式でリンクが生成されていました。

<a href="/{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">...</a>

ここで、$src_htmlsrcLink .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_htmlsrcLink .File.Path | htmlまたはsrcLink .Filename | htmlの結果であり、srcLink関数が絶対パスを返すように設計されているため、テンプレート内でさらにスラッシュを追加する必要がありませんでした。

この修正により、生成されるURLは//を含まなくなり、godocの検索結果ページからソースコードへのリンクが正しく機能するようになります。

関連リンク

参考にした情報源リンク