[インデックス 12916] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/http
パッケージの example_test.go
ファイルに、http.FileServer
と http.StripPrefix
の使用例を追加するものです。具体的には、src/pkg/net/http/example_test.go
ファイルに5行の追加が行われました。
コミット
commit acb550504fa77e16070405fd5a89770a416de75b
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Fri Apr 20 00:41:10 2012 +0800
net/http: add example for FileServer to mention StripPrefix
Fixes #3530.
R=golang-dev, rsc, bradfitz
CC=golang-dev
https://golang.org/cl/6032052
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/acb550504fa77e16070405fd5a89770a416de75b
元コミット内容
net/http: add example for FileServer to mention StripPrefix
Fixes #3530.
変更の背景
このコミットの背景には、net/http
パッケージの FileServer
を使用して静的ファイルを配信する際に、特定のURLパスからファイルを配信するための一般的なパターンである http.StripPrefix
との組み合わせ方について、ユーザーが混乱していたという問題があったと考えられます。コミットメッセージにある "Fixes #3530" は、この変更がGoのIssueトラッカーで報告された問題3530を解決するものであることを示しています。
http.FileServer
は指定されたディレクトリのファイルをそのまま提供しますが、ウェブアプリケーションではしばしば、特定のURLプレフィックス(例: /static/
)の下にファイルを配置し、そのプレフィックスを内部的なファイルパスから取り除いてから FileServer
に渡す必要があります。この「プレフィックスの除去」の概念が、特に初心者にとっては直感的ではない場合があり、公式の例が不足していたことで、誤った実装や理解不足が生じていた可能性があります。
このコミットは、そのような一般的なユースケースに対する明確な例を提供することで、開発者が net/http
パッケージをより効果的に利用できるようにすることを目的としています。
前提知識の解説
このコミットを理解するためには、Go言語の net/http
パッケージにおける以下の基本的な概念を理解しておく必要があります。
net/http
パッケージ: Go言語の標準ライブラリで、HTTPクライアントとサーバーの実装を提供します。ウェブアプリケーションを構築する上で中心的な役割を担います。http.Handler
インターフェース: HTTPリクエストを処理するためのインターフェースです。ServeHTTP(ResponseWriter, *Request)
メソッドを実装することで、任意の型がHTTPハンドラとして機能できます。http.Handle
関数: 特定のURLパス(パターン)とhttp.Handler
を関連付け、HTTPリクエストがそのパスにマッチした際に指定されたハンドラが呼び出されるように登録します。http.FileServer(root http.FileSystem) http.Handler
: 指定されたhttp.FileSystem
からファイルをHTTPリクエストに応じて提供するhttp.Handler
を返します。これは静的ファイル(HTML、CSS、JavaScript、画像など)を配信する際に非常に便利です。http.Dir(dir string) FileSystem
: オペレーティングシステムのファイルシステム上の指定されたディレクトリをhttp.FileSystem
インターフェースとしてラップします。これにより、http.FileServer
が実際のディスク上のファイルにアクセスできるようになります。http.StripPrefix(prefix string, h http.Handler) http.Handler
: この関数は、http.Handler
をラップし、そのハンドラにリクエストを渡す前に、リクエストURLのパスから指定されたprefix
を取り除きます。これは、URLパスとファイルシステム上のパスの間にずれがある場合に特に重要です。例えば、/tmpfiles/somefile
というURLで/tmp/somefile
を提供したい場合、/tmpfiles/
というプレフィックスを取り除く必要があります。StripPrefix
は、指定されたプレフィックスで始まらないパスへのリクエストに対しては、HTTP 404 (Not Found) エラーを返します。
技術的詳細
http.FileServer
は、その root
引数で指定された http.FileSystem
のルートディレクトリを基準として、リクエストされたURLパスに対応するファイルを検索します。例えば、http.FileServer(http.Dir("/tmp"))
の場合、/somefile.txt
というリクエストが来ると、/tmp/somefile.txt
を探します。
しかし、ウェブアプリケーションでは、しばしば特定のURLパスの下に静的ファイルをまとめて配置したい場合があります。例えば、/tmpfiles/
というURLパスで /tmp
ディレクトリの内容を公開したいとします。もし単純に http.Handle("/tmpfiles/", http.FileServer(http.Dir("/tmp")))
とすると、/tmpfiles/somefile
というリクエストが来た際に、FileServer
は /tmp/tmpfiles/somefile
を探してしまい、意図した動作になりません。
ここで http.StripPrefix
が必要になります。http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))
のように組み合わせることで、以下のようになります。
- クライアントから
/tmpfiles/somefile
というリクエストが来る。 http.Handle("/tmpfiles/", ...)
によって、このリクエストが登録されたハンドラにルーティングされる。- ハンドラは
http.StripPrefix
によってラップされているため、まずリクエストURLパスから/tmpfiles/
が取り除かれる。結果として、内部的なパスは/somefile
となる。 http.StripPrefix
は、この修正されたパス (/somefile
) を持つリクエストを、ラップしているhttp.FileServer(http.Dir("/tmp"))
に渡す。http.FileServer
は、そのルートディレクトリ/tmp
を基準に/somefile
を探し、結果として/tmp/somefile
を提供する。
この一連の流れが、URLパスと実際のファイルパスのマッピングを正しく行うために不可欠です。このコミットで追加された例は、この一般的なパターンを明確に示し、開発者が FileServer
を適切に利用できるようにするためのものです。
コアとなるコードの変更箇所
--- a/src/pkg/net/http/example_test.go
+++ b/src/pkg/net/http/example_test.go
@@ -49,3 +49,8 @@ func ExampleGet() {
res.Body.Close()
fmt.Printf("%s", robots)
}
+
+func ExampleFileServer() {
+ // we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
+ http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
+}
コアとなるコードの解説
追加されたコードは ExampleFileServer
という関数で、GoのテストパッケージにおけるExample関数として機能します。Example関数は、パッケージのドキュメントにコード例として表示され、go test
コマンドで実行可能であり、その出力が期待される出力と一致するかどうかも検証されます。これにより、ドキュメントの正確性とコードの動作が保証されます。
func ExampleFileServer() {
// we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}
func ExampleFileServer() { ... }
: これはGoのExample関数です。この関数内のコードは、net/http
パッケージのドキュメントにFileServer
の使用例として表示されます。// we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
: このコメントは、なぜStripPrefix
を使用するのかを簡潔に説明しています。/tmpfiles/somefile
というURLパスが、実際のファイルシステム上の/tmp/somefile
にマッピングされるようにするためです。http.Handle("/tmpfiles/", ...)
: これは、/tmpfiles/
で始まるすべてのHTTPリクエストを処理するためのハンドラを登録しています。末尾のスラッシュ (/
) は、このパスとそのサブパスの両方をカバーすることを示します。http.StripPrefix("/tmpfiles/", ...)
: ここがこの例の核心です。- 最初の引数
"/tmpfiles/"
は、リクエストURLパスから取り除くプレフィックスを指定します。 - 二番目の引数
http.FileServer(http.Dir("/tmp"))
は、プレフィックスが取り除かれた後のリクエストを処理する実際のハンドラです。
- 最初の引数
http.FileServer(http.Dir("/tmp"))
: これは、/tmp
ディレクトリの内容を静的ファイルとして提供するhttp.Handler
を作成します。http.Dir("/tmp")
は、オペレーティングシステムの/tmp
ディレクトリをhttp.FileSystem
インターフェースとしてラップします。
この一行のコードは、net/http
を使って特定のURLパスから静的ファイルを効率的かつ安全に提供するための、非常に一般的で重要なパターンを簡潔に示しています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/acb550504fa77e16070405fd5a89770a416de75b
- Gerrit Change-Id: https://golang.org/cl/6032052
参考にした情報源リンク
- Go
net/http
パッケージのドキュメント (一般的な情報): http.FileServer
とhttp.StripPrefix
の解説記事:- Go言語のExampleテストに関する情報: