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

[インデックス 11788] ファイルの概要

このコミットは、Go言語の標準ライブラリである net/http パッケージのドキュメント内の誤った参照を修正するものです。具体的には、http.HandleFunc の使用例において、r.URL.RawPath ではなく r.URL.Path を参照するように変更されています。これにより、ドキュメントの正確性が向上し、ユーザーが net/http パッケージを正しく理解し、利用できるようになります。

コミット

commit 0846e275a88b1b0b92a8cacab5b7e4cfc747e072
Author: Bjorn Tipling <bjorn.tipling@gmail.com>
Date:   Fri Feb 10 22:39:57 2012 -0200

    net/http: fix reference to URL.RawPath in docs
    
    R=go.peter.90, n13m3y3r, gustavo
    CC=golang-dev
    https://golang.org/cl/5655053

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/0846e275a88b1b0b92a8cacab5b7e4cfc747e072

元コミット内容

net/http: fix reference to URL.RawPath in docs

このコミットは、net/http パッケージのドキュメント内で URL.RawPath への参照が誤っていたのを修正するものです。

変更の背景

Go言語の net/http パッケージは、HTTPクライアントとサーバーの実装を提供します。このパッケージのドキュメントには、http.HandleFunc を使用してHTTPリクエストを処理する例が含まれています。元々のドキュメントのコード例では、リクエストのURLパスを取得するために r.URL.RawPath が使用されていました。

しかし、URL.RawPath はURLのパス部分がエンコードされたままの形式(例: %2F のようなパーセントエンコーディングを含む)を保持します。一方、URL.Path はパーセントエンコーディングがデコードされた形式(例: /)を提供します。通常、HTTPハンドラでユーザーに表示したり、内部処理で使用したりする際には、デコードされた URL.Path の方が適切です。特に、html.EscapeString のような関数でエスケープ処理を行う場合、デコードされたパスをエスケープする方が意図した動作になります。

このコミットは、ドキュメントのコード例が net/http パッケージの一般的な使用パターンとベストプラクティスに沿うように、RawPath から Path への修正を行いました。これにより、ドキュメントを参照する開発者が誤ったパスの扱い方を学ぶことを防ぎ、より堅牢で安全なアプリケーション開発を促進します。

前提知識の解説

Go言語の net/http パッケージ

net/http パッケージは、Go言語でHTTPクライアントとサーバーを構築するための基本的な機能を提供します。ウェブアプリケーションやAPIサーバーを開発する際に中心的に使用されます。

  • http.Request: HTTPリクエストを表す構造体です。クライアントからのリクエストに関する情報(メソッド、URL、ヘッダー、ボディなど)を含みます。
  • http.ResponseWriter: HTTPレスポンスを書き込むためのインターフェースです。サーバーがクライアントに返すデータ(ステータスコード、ヘッダー、ボディなど)を書き込みます。
  • http.HandleFunc(pattern string, handler func(ResponseWriter, *Request)): 指定されたパターン(URLパス)に対してHTTPハンドラ関数を登録します。
  • http.ListenAndServe(addr string, handler Handler): 指定されたアドレスでHTTPサーバーを起動します。

url.URL 構造体

http.Request 構造体には URL フィールドがあり、これは url.URL 型です。url.URL 構造体は、URLの各コンポーネント(スキーム、ホスト、パス、クエリ、フラグメントなど)を解析して保持します。

  • URL.Path: URLのパス部分を表す文字列です。これは、パーセントエンコーディングがデコードされた後のパスです。例えば、/foo%2Fbar/foo/bar となります。
  • URL.RawPath: URLのパス部分を表す文字列です。これは、パーセントエンコーディングがデコードされていない生のパスです。例えば、/foo%2Fbar/foo%2Fbar のままです。

html.EscapeString 関数

html.EscapeString(s string) は、HTMLドキュメントに安全に埋め込むために、文字列 s 内の特殊文字(<, >, &, ', ")を対応するHTMLエンティティ(&lt;, &gt;, &amp;, &#39;, &quot;)に変換する関数です。これにより、クロスサイトスクリプティング(XSS)攻撃などのセキュリティ脆弱性を防ぐことができます。

技術的詳細

このコミットの技術的なポイントは、URL.PathURL.RawPath の使い分けにあります。

  • URL.RawPath の用途: RawPath は、URLのパス部分がエンコードされた元の形式を保持しているため、URLをそのまま再構築する場合や、エンコードされたパス自体に意味がある場合(例えば、特定のルーティングロジックがエンコードされたパスに依存する場合)に利用されます。しかし、通常はユーザーに表示したり、ファイルシステムパスとして利用したりする際には、デコードされた形式が望ましいです。

  • URL.Path の用途: Path は、パーセントエンコーディングがデコードされた後のパスを提供します。これは、ほとんどのアプリケーションでURLパスを処理する際に期待される形式です。例えば、/users/%E3%83%86%E3%82%B9%E3%83%88 のようなURLの場合、RawPath/users/%E3%83%86%E3%82%B9%E3%83%88 のままですが、Path/users/テスト となります。

ドキュメントの例では、fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath)) のように、取得したパスを html.EscapeString でエスケープして出力しています。もし RawPath を使用した場合、例えばURLが /foo%2Fbar であったとすると、RawPath/foo%2Fbar となり、これをエスケープすると Hello, "/foo%2Fbar" のように表示されます。しかし、意図としては /foo/bar のようなデコードされたパスを表示したい場合が多いでしょう。

URL.Path を使用することで、URLが /foo%2Fbar であっても Path/foo/bar となり、これをエスケープして出力すると Hello, "/foo/bar" となり、より自然で期待される表示になります。この修正は、ドキュメントのコード例が net/http パッケージの一般的な利用シナリオとセキュリティプラクティスに合致するようにするための重要な変更です。

コアとなるコードの変更箇所

--- a/src/pkg/net/http/doc.go
+++ b/src/pkg/net/http/doc.go
@@ -60,7 +60,7 @@ Handle and HandleFunc add handlers to DefaultServeMux:
 	http.Handle("/foo", fooHandler)

 	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath))
+		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
 	})

 	log.Fatal(http.ListenAndServe(":8080", nil))

コアとなるコードの解説

変更は src/pkg/net/http/doc.go ファイル内の http.HandleFunc の使用例にあります。

元のコード:

fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath))

修正後のコード:

fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))

この変更は、r.URL.RawPathr.URL.Path に置き換えることで、HTTPリクエストのURLパスを処理する際の動作を修正しています。

  • r.URL.RawPath: リクエストURLのパス部分を、パーセントエンコーディングがデコードされていない「生」の形式で取得します。例えば、URLが http://example.com/path%2Fwith%2Fslash の場合、RawPath/path%2Fwith%2Fslash となります。
  • r.URL.Path: リクエストURLのパス部分を、パーセントエンコーディングがデコードされた形式で取得します。上記の例の場合、Path/path/with/slash となります。

ドキュメントの例では、このパスを html.EscapeString でエスケープしてから出力しています。ユーザーに表示する目的や、一般的なパス処理の文脈では、デコードされた Path を使用する方が自然であり、意図した結果が得られます。この修正により、ドキュメントのコード例がより実用的で、Goの net/http パッケージの推奨される使用方法を反映するようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (pkg.go.dev)
  • Go言語のソースコード (github.com/golang/go)
  • Go言語のコミット履歴 (github.com/golang/go/commits)
  • Go言語のコードレビューシステム (golang.org/cl/5655053)