[インデックス 10354] ファイルの概要
このコミットは、Go言語のドキュメンテーションツールである godoc
におけるリモート検索機能のバグ修正に関するものです。具体的には、リモート検索時に使用されるURLが正しく構築されていなかった問題を解決し、-html
フラグと組み合わせた際にもHTML形式での検索結果が正しく取得できるように改善しています。
コミット
- コミットハッシュ:
e8188c160762f654369cdba535324a97df6aed22
- 作者: Robert Griesemer gri@golang.org
- コミット日時: 2011年11月11日 金曜日 16:59:47 -0800
- 変更ファイル:
src/cmd/godoc/godoc.go
src/cmd/godoc/main.go
- 変更概要:
src/cmd/godoc/godoc.go
に14行追加、src/cmd/godoc/main.go
から3行削除、合計15行の追加と3行の削除。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e8188c160762f654369cdba535324a97df6aed22
元コミット内容
godoc: fix remote search (use correct URL)
Also works now together with -html, as in:
godoc -html -q Sin
for an html result.
Fixes #2435.
R=iant
CC=golang-dev
https://golang.org/cl/5375074
変更の背景
このコミットは、godoc
コマンドのリモート検索機能が正しく動作しないというバグ(Issue #2435)を修正するために行われました。元の実装では、リモートサーバーに検索リクエストを送信する際のURLの構築に問題があり、特に検索クエリに特殊文字が含まれる場合や、HTML形式での結果を要求する -html
フラグが使用された場合に、期待通りの結果が得られませんでした。
具体的には、以下の問題が考えられます。
- URLエンコーディングの不備: 検索クエリ文字列がURLの一部として送信される際、スペースや記号などの特殊文字が適切にエンコードされていないと、サーバー側で正しく解釈されず、検索が失敗したり、意図しない結果が返されたりします。
- HTML出力の考慮不足:
godoc -html -q <query>
のように-html
フラグを使用してHTML形式の出力を要求した場合、リモート検索のURLがその要求を適切に反映していなかった可能性があります。例えば、テキスト形式の検索結果を要求するURLとHTML形式の検索結果を要求するURLが異なっていたにもかかわらず、常にテキスト形式のURLが使用されていた、といった状況が考えられます。
このコミットは、これらの問題を解決し、godoc
のリモート検索機能がより堅牢で、ユーザーの期待通りに動作するようにすることを目的としています。
前提知識の解説
godoc
godoc
は、Go言語の公式ドキュメンテーションツールです。Goのソースコードからコメントや宣言を解析し、パッケージ、関数、型などのドキュメンテーションを生成・表示します。ローカルのGoインストールに含まれるパッケージのドキュメントを表示するだけでなく、golang.org
などのリモートサーバー上のドキュメントを検索する機能も持っています。
- ローカルドキュメントの表示:
godoc fmt
のように実行すると、標準ライブラリのfmt
パッケージのドキュメントを表示します。 - HTTPサーバーモード:
godoc -http=:8000
のように実行すると、ローカルでドキュメンテーションサーバーを起動し、ウェブブラウザからアクセスしてドキュメントを閲覧できます。これはgolang.org/pkg
のようなインターフェースを提供します。 - リモート検索:
godoc -q <query>
のように実行すると、リモートのgolang.org
などのサーバーに対して検索クエリを送信し、関連するドキュメントを検索します。
URLエンコーディング
URL(Uniform Resource Locator)は、インターネット上のリソースを一意に識別するための文字列です。URLには、特定の文字セット(英数字、一部の記号)しか使用できません。スペースや日本語などの非ASCII文字、あるいはURLの構文で特別な意味を持つ文字(例: ?
, &
, /
, #
)をURLに含める場合、それらの文字は「パーセントエンコーディング」(Percent-encoding)と呼ばれる形式で変換される必要があります。
例えば、スペースは %20
に、?
は %3F
にエンコードされます。Go言語では、net/url
パッケージの QueryEscape
関数がこの処理を提供します。
HTTP GETリクエストとクエリパラメータ
ウェブブラウザやHTTPクライアントがサーバーから情報を取得する際によく使われるのがHTTP GETリクエストです。GETリクエストでは、クライアントがサーバーに送るデータ(検索クエリなど)をURLの末尾に「クエリパラメータ」として含めることができます。クエリパラメータは ?
の後に キー=値
の形式で記述され、複数のパラメータは &
で区切られます。
例: https://example.com/search?q=Go+language&page=1
ここで q
と page
がクエリパラメータです。
技術的詳細
このコミットの技術的な核心は、godoc
のリモート検索機能が、検索クエリと出力形式(テキストまたはHTML)に応じて適切なURLを生成するように修正された点にあります。
以前の remoteSearch
関数では、検索URLが以下のようにハードコードされていました。
search := "/search?f=text&q=" + url.QueryEscape(query)
このコードには以下の問題がありました。
f=text
の固定: 常にf=text
というクエリパラメータが使用されており、HTML形式の検索結果を要求する-html
フラグが指定されても、それがURLに反映されませんでした。godoc -html -q Sin
のようなコマンドを実行しても、サーバーはテキスト形式の検索結果を返そうとするため、クライアント側でHTMLとして解釈しようとすると問題が発生します。- URL構築ロジックの分散: 検索URLの構築ロジックが
remoteSearch
関数内に直接記述されており、将来的に検索パラメータやURL構造が変更された場合に、修正が困難になる可能性がありました。
このコミットでは、これらの問題を解決するために、新しいヘルパー関数 remoteSearchURL
が導入されました。
remoteSearchURL
関数の導入
remoteSearchURL
関数は、検索クエリ文字列 (query
) と、HTML形式の結果を要求するかどうかを示すブール値 (html
) を引数として受け取ります。この関数は、これらの引数に基づいて適切な検索URLを生成し、返します。
func remoteSearchURL(query string, html bool) string {
s := "/search?m=text&q=" // デフォルトはテキスト形式
if html {
s = "/search?q=" // HTML形式の場合は異なるパス
}
return s + url.QueryEscape(query) // クエリを適切にエンコード
}
この変更により、以下の点が改善されました。
- 出力形式の動的な切り替え:
html
引数に基づいて、m=text
パラメータの有無を切り替えることで、サーバーに対してテキスト形式またはHTML形式の検索結果を適切に要求できるようになりました。 - URLエンコーディングの徹底:
url.QueryEscape(query)
を使用することで、検索クエリに含まれる特殊文字が常に正しくURLエンコードされるようになりました。これにより、検索クエリがサーバーに正確に伝達され、検索の信頼性が向上します。 - 関心の分離: URL構築ロジックが
remoteSearchURL
関数にカプセル化されたことで、remoteSearch
関数はURLの取得に専念できるようになり、コードの可読性と保守性が向上しました。
main.go
からの net/url
インポートの削除
src/cmd/godoc/main.go
から net/url
パッケージのインポートが削除されました。これは、以前 main.go
内の remoteSearch
関数で直接 url.QueryEscape
を使用していたためですが、新しい remoteSearchURL
関数が godoc.go
に移動し、そこで net/url
をインポートするようになったため、main.go
では不要になったためです。これは、依存関係の整理とコードのクリーンアップの一環です。
コアとなるコードの変更箇所
src/cmd/godoc/godoc.go
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -16,6 +16,7 @@ import (
"io"
"log"
"net/http"
+ "net/url" // net/url パッケージのインポートを追加
"os"
"path"
"path/filepath"
@@ -845,6 +846,19 @@ func getPageInfoMode(r *http.Request) (mode PageInfoMode) {
return
}
+// remoteSearchURL returns the search URL for a given query as needed by
+// remoteSearch. If html is set, an html result is requested; otherwise
+// the result is in textual form.
+// Adjust this function as necessary if modeNames or FormValue parameters
+// change.
+func remoteSearchURL(query string, html bool) string {
+ s := "/search?m=text&q=" // テキスト形式のデフォルトパス
+ if html {
+ s = "/search?q=" // HTML形式のパス
+ }
+ return s + url.QueryEscape(query) // クエリをエンコードして結合
+}
+
type PageInfo struct {
Dirname string // directory containing the package
PList []string // list of package names found
src/cmd/godoc/main.go
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -38,7 +38,6 @@ import (
"log"
"net/http"
_ "net/http/pprof" // to serve /debug/pprof/*
- "net/url" // この行が削除された
"os"
"path"
"path/filepath"
@@ -165,8 +164,6 @@ func loggingHandler(h http.Handler) http.Handler {
}
func remoteSearch(query string) (res *http.Response, err error) {
- search := "/search?f=text&q=" + url.QueryEscape(query) // この行が削除された
-
// list of addresses to try
var addrs []string
if *serverAddr != "" {
@@ -180,6 +177,7 @@ func remoteSearch(query string) (res *http.Response, err error) {\n }\n \n // remote search
+ search := remoteSearchURL(query, *html) // 新しい remoteSearchURL 関数を呼び出すように変更
for _, addr := range addrs {\n url := "http://" + addr + search\n res, err = http.Get(url)\n```
## コアとなるコードの解説
### `src/cmd/godoc/godoc.go` の変更
1. **`net/url` のインポート**: `remoteSearchURL` 関数内で `url.QueryEscape` を使用するため、`net/url` パッケージがインポートされました。
2. **`remoteSearchURL` 関数の追加**:
* この関数は、リモート検索のためのURLを構築する責任を持ちます。
* `query` (検索文字列) と `html` (HTML形式の結果を要求するかどうか) の2つの引数を受け取ります。
* `html` が `true` の場合、URLのパスは `/search?q=` となり、HTML形式の検索結果を要求します。
* `html` が `false` の場合(またはデフォルト)、URLのパスは `/search?m=text&q=` となり、テキスト形式の検索結果を要求します。
* 最後に、`url.QueryEscape(query)` を使って `query` 文字列を適切にURLエンコードし、構築されたパスに結合して返します。これにより、検索クエリに含まれる特殊文字が正しく処理されます。
### `src/cmd/godoc/main.go` の変更
1. **`net/url` のインポート削除**: `remoteSearch` 関数内で直接 `url.QueryEscape` を呼び出す必要がなくなったため、`main.go` から `net/url` のインポートが削除されました。これは、依存関係を `godoc.go` に集約し、コードのモジュール性を高めるための変更です。
2. **`remoteSearch` 関数の変更**:
* 以前の `search := "/search?f=text&q=" + url.QueryEscape(query)` というハードコードされたURL構築ロジックが削除されました。
* 代わりに、新しく追加された `remoteSearchURL(query, *html)` 関数が呼び出され、適切な検索URLが取得されるようになりました。ここで `*html` は、コマンドライン引数で指定された `-html` フラグの値(ブール値)を参照しています。これにより、ユーザーが `-html` フラグを指定したかどうかに応じて、正しい形式のURLがリモートサーバーに送信されるようになります。
これらの変更により、`godoc` のリモート検索機能は、より正確なURLを生成し、HTML形式の検索結果も正しく扱えるようになりました。
## 関連リンク
* **Go Issue #2435**: [https://code.google.com/p/go/issues/detail?id=2435](https://code.google.com/p/go/issues/detail?id=2435) (元のGoogle CodeのIssueトラッカーへのリンクですが、現在はGitHubに移行しています。GitHub上の対応するIssueは [https://github.com/golang/go/issues/2435](https://github.com/golang/go/issues/2435) です。)
* **Go CL 5375074**: [https://golang.org/cl/5375074](https://golang.org/cl/5375074) (GoのコードレビューシステムであるGerritへのリンク)
## 参考にした情報源リンク
* Go言語公式ドキュメンテーション: [https://golang.org/doc/](https://golang.org/doc/)
* `net/url` パッケージのドキュメンテーション: [https://pkg.go.dev/net/url](https://pkg.go.dev/net/url)
* `godoc` コマンドのドキュメンテーション (Goのインストールに含まれる): `go doc cmd/godoc` または `godoc -h`
* HTTP GET メソッドとクエリパラメータに関する一般的な情報 (MDN Web Docsなど)
* URLエンコーディングに関する一般的な情報 (RFC 3986など)
* GitHub上のGoリポジトリ: [https://github.com/golang/go](https://github.com/golang/go)
* Go Issue #2435 (GitHub): [https://github.com/golang/go/issues/2435](https://github.com/golang/go/issues/2435)