[インデックス 12764] ファイルの概要
このコミットは、Go言語のドキュメンテーションツールであるcmd/godoc
におけるカスタムパスのリダイレクト処理を正規化(canonicalize)するための変更です。具体的には、末尾のスラッシュの有無にかかわらず、同じリソースへのパスが統一された形式にリダイレクトされるように改善されています。これにより、ユーザーが/ref
と/doc/reference.html
のような異なるパスでアクセスした場合でも、最終的に/ref/
のような正規化されたパスにリダイレクトされるようになります。
コミット
commit 849ad2d0cac9b3ee97b3d331ca6e556a6073d94d
Author: Andrew Gerrand <adg@golang.org>
Date: Tue Mar 27 12:44:17 2012 +1100
cmd/godoc: canonicalize custom path redirects
For example, /ref and /doc/reference.html now both redirect to /ref/.
Fixes #3401.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5916044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/849ad2d0cac9b3ee97b3d331ca6e556a6073d94d
元コミット内容
cmd/godoc: canonicalize custom path redirects
For example, /ref and /doc/reference.html now both redirect to /ref/.
Fixes #3401.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5916044
変更の背景
この変更の背景には、godoc
が提供するドキュメントパスのリダイレクト処理における一貫性の問題がありました。以前のgodoc
では、特定のパス(例: /ref
)がリダイレクトされる際に、末尾のスラッシュの有無によって異なる挙動を示す可能性がありました。例えば、/ref
と/ref/
が同じリソースを指す場合でも、リダイレクト先が統一されていないと、ユーザー体験の低下や、SEO(検索エンジン最適化)上の問題を引き起こす可能性があります。
このコミットは、godoc
がカスタムパスのリダイレクトを行う際に、末尾のスラッシュの有無を考慮し、常に正規化された(canonicalな)パスにリダイレクトするように修正することを目的としています。これにより、/ref
と/doc/reference.html
のような異なる入力パスが、最終的に/ref/
のような単一の正規化されたパスにリダイレクトされるようになり、より予測可能で一貫性のある挙動が実現されます。
コミットメッセージに記載されているFixes #3401
は、Goプロジェクトの内部的な課題追跡システムにおける特定のバグまたは改善要求に対応するものであると考えられます。
前提知識の解説
godoc
godoc
は、Go言語のソースコードからドキュメンテーションを生成し、HTTPサーバーとして提供するツールです。Goのコードに記述されたコメントや宣言から自動的にドキュメントを抽出し、開発者がブラウザを通じて簡単に参照できるようにします。Go言語の標準ライブラリのドキュメントもgodoc
によって生成され、pkg.go.dev(旧golang.org/pkg)で公開されています。
Canonicalization (正規化)
Canonicalization(正規化)とは、複数の異なる形式で表現されうるデータやリソースを、単一の標準的な形式に変換するプロセスを指します。ウェブの文脈では、URLの正規化がよく行われます。例えば、http://example.com/page
とhttp://example.com/page/
、http://www.example.com/page
がすべて同じコンテンツを指す場合、これらをhttp://example.com/page/
のような単一の「正規URL」に統一することで、検索エンジンの評価分散を防ぎ、ユーザー体験を向上させることができます。
パスリダイレクト
パスリダイレクトは、ウェブサーバーが特定のURLへのリクエストを受け取った際に、そのリクエストを別のURLに自動的に転送する仕組みです。これは、ページの移動、URL構造の変更、または複数のURLを単一のリソースに統合する際などに使用されます。HTTPステータスコード3xx(例: 301 Moved Permanently, 302 Found)がリダイレクトのために使用されます。
技術的詳細
このコミットは、src/cmd/godoc/godoc.go
ファイル内のmetadataFor
関数に変更を加えています。metadataFor
関数は、与えられた相対パス(relpath
)に対応するメタデータ(*Metadata
)を取得する役割を担っています。
変更前は、metadataFor
関数はdocMetadata
から直接relpath
に対応するメタデータを検索していました。しかし、この方法では、例えば/ref
と/ref/
のように末尾のスラッシュの有無が異なるパスが、同じリソースを指しているにもかかわらず、別々のエントリとして扱われる可能性がありました。
変更後のコードでは、以下のロジックが追加されています。
- まず、元の
relpath
でメタデータが存在するかどうかを確認します。存在すれば、それを返します。 - もし元の
relpath
でメタデータが見つからなかった場合、末尾のスラッシュの有無を反転させて再試行します。- もし
relpath
が末尾にスラッシュを持っている場合(例:/ref/
)、スラッシュを取り除いたパス(例:/ref
)で再検索します。 - もし
relpath
が末尾にスラッシュを持っていない場合(例:/ref
)、スラッシュを追加したパス(例:/ref/
)で再検索します。
- もし
この変更により、metadataFor
関数は、末尾のスラッシュの有無にかかわらず、同じ論理的なパスに対応するメタデータを適切に取得できるようになり、リダイレクト処理の一貫性が向上します。
コアとなるコードの変更箇所
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -1315,7 +1315,18 @@ func refreshMetadataLoop() {
//
func metadataFor(relpath string) *Metadata {
if m, _ := docMetadata.get(); m != nil {
- return m.(map[string]*Metadata)[relpath]
+ meta := m.(map[string]*Metadata)
+ // If metadata for this relpath exists, return it.
+ if p := meta[relpath]; p != nil {
+ return p
+ }
+ // Try with or without trailing slash.
+ if strings.HasSuffix(relpath, "/") {
+ relpath = relpath[:len(relpath)-1]
+ } else {
+ relpath = relpath + "/"
+ }
+ return meta[relpath]
}
return nil
}
コアとなるコードの解説
変更はsrc/cmd/godoc/godoc.go
ファイルのmetadataFor
関数内で行われています。
func metadataFor(relpath string) *Metadata {
if m, _ := docMetadata.get(); m != nil {
meta := m.(map[string]*Metadata)
// If metadata for this relpath exists, return it.
if p := meta[relpath]; p != nil {
return p
}
// Try with or without trailing slash.
if strings.HasSuffix(relpath, "/") {
relpath = relpath[:len(relpath)-1]
} else {
relpath = relpath + "/"
}
return meta[relpath]
}
return nil
}
meta := m.(map[string]*Metadata)
:docMetadata
から取得したメタデータマップをmeta
変数にキャストしています。if p := meta[relpath]; p != nil
: まず、引数として渡されたrelpath
(例:/ref
)がそのままマップのキーとして存在するかどうかを確認します。もし存在すれば、そのメタデータをすぐに返します。これは、最も直接的なマッチングを優先するためです。if strings.HasSuffix(relpath, "/")
: もし最初の試行でメタデータが見つからなかった場合、パスの末尾にスラッシュがあるかどうかをstrings.HasSuffix
関数で確認します。relpath = relpath[:len(relpath)-1]
: もしスラッシュがある場合(例:/ref/
)、そのスラッシュを取り除きます(例:/ref
)。relpath = relpath + "/"
: もしスラッシュがない場合(例:/ref
)、スラッシュを追加します(例:/ref/
)。
return meta[relpath]
: スラッシュの有無を反転させた新しいrelpath
で再度メタデータを検索し、その結果を返します。
このロジックにより、metadataFor
関数は、/ref
と/ref/
のようなパスのバリエーションを透過的に処理し、どちらの形式でリクエストが来ても適切なメタデータを返すことができるようになります。これにより、godoc
のリダイレクト処理がより堅牢でユーザーフレンドリーになります。
関連リンク
- Go言語公式サイト: https://go.dev/
- Go言語のドキュメンテーション(pkg.go.dev): https://pkg.go.dev/
godoc
コマンドのドキュメンテーション(Goコマンドリファレンス内): https://go.dev/cmd/godoc/
参考にした情報源リンク
- GitHubコミットページ: https://github.com/golang/go/commit/849ad2d0cac9b3ee97b3d331ca6e556a6073d94d
- Go CL 5916044: https://golang.org/cl/5916044
Fixes #3401
について: このコミットが修正したとされる#3401
は、Goプロジェクトの内部的な課題追跡システム(おそらく当時のGo issue tracker)の番号であると考えられます。現在のGitHubのissue trackerで直接この番号を検索しても、当時の関連情報がすぐに見つからない場合があります。これは、issue trackingシステムが時間とともに変更されたり、特定のissueが非公開であったりするためです。