[インデックス 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テストに関する情報: