http.Handler インターフェース
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 77/107。
http.Handler インターフェースは、Go の Web サーバーアーキテクチャの基盤です。HTTP リクエストの処理方法を定義し、それを implement する任意の型で Web リクエストを処理できます。
このインターフェースは驚くほどシンプルです。
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}ServeHTTPメソッドを持つ任意の型は、HTTPリクエストを処理できます。以下はカスタムhandlerです。
type GreetHandler struct {
Greeting string
}
func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}この handler はサーバーで直接使用できます:
handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)より単純なケースでは、Go は http.HandlerFunc を提供します。これは通常の関数をハンドラーに変換できる型です。
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
http.Handle("/hello", http.HandlerFunc(hello))このインターフェースの強力さは、handler が他の handler をラップできると分かると明らかになります。これにより、元の handler のロジックを変更せずに、ロギング、認証、その他の横断的関心事を追加する middleware パターンを実現できます。
チャレンジ
簡単Web リクエストがどのように処理されるかをシミュレートする、シンプルな HTTP handler system を構築しましょう!この環境では実際の HTTP サーバーを実行できないため、http.Handler interface を implement する handlers を作成し、モックの request/response オブジェクトを使ってそれらがどのようにリクエストを処理するかを示します。
コードを 2 つのファイルに整理します。
handlers.go: カスタム HTTP handlers を定義します。HTTP response に書き込まれる内容を captures する
MockResponseWriterstruct を Create します。response body を string として保存し、data を body に appends するWrite(data []byte) (int, error)method を implement する必要があります。accumulated response を取得するためのBody() stringmethod も Add します。HTTP request をシミュレートするため、
PathとMethodの string field を持つMockRequeststruct を Create します。次に、
http.Handlerinterface pattern を implement する 2 つの handler struct を Create します(*MockResponseWriterと*MockRequestを受け取るServeHTTPmethod を持たせます)。WelcomeHandler(Messagefield を持つ)- message に request path を followed した内容を書き込みますMethodHandler- request method に based して different な response を書き込みます。GET には"Fetching data"、POST には"Creating resource"、それ以外には"Method not supported"を使います
main.go: handlers を通して requests を処理します。handler type(
welcomeまたはmethod)を読み取り、続けて request details を読み取ります。welcome handler の場合は、welcome message も読み取ります。appropriate な handler を Create し、mock request を構築して、
ServeHTTPを call して処理します。response body を出力します。
次の inputs が提供されます。
- Line 1: Handler type(
welcomeまたはmethod) - Line 2: Request path
- Line 3: Request method
- Line 4(welcome の場合のみ): Welcome message
たとえば、次の入力が与えられた場合:
welcome
/home
GET
Hello fromoutput は次のようになります。
Hello from /homeまた、次の入力が与えられた場合:
method
/api/users
POSToutput は次のようになります。
Creating resourceさらに、次の入力が与えられた場合:
method
/api/data
GEToutput は次のようになります。
Fetching dataさらに、次の入力が与えられた場合:
method
/api/items
DELETEoutput は次のようになります。
Method not supportedこの challenge は、http.Handler interface の core concept を示しています。つまり、ServeHTTP method を持つ任意の type が requests を handle できます。実際の applications では、http.ResponseWriter と *http.Request は Go の standard library から提供されますが、handlers を implementing する pattern はまったく同じままです。
自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// ハンドラータイプを読み取る
scanner.Scan()
handlerType := scanner.Text()
// リクエストパスを読み取る
scanner.Scan()
path := scanner.Text()
// リクエストメソッドを読み取る
scanner.Scan()
method := scanner.Text()
// モックリクエストを作成する
request := &MockRequest{
Path: path,
Method: method,
}
// モックレスポンスライターを作成する
response := &MockResponseWriter{}
// TODO: handlerTypeに基づいて、適切なハンドラーを作成する
// handlerTypeが"welcome"の場合、ウェルカムメッセージを読み取り、WelcomeHandlerを作成する
// handlerTypeが"method"の場合、MethodHandlerを作成する
// ハンドラーのServeHTTPをresponseとrequestで呼び出す
if handlerType == "welcome" {
scanner.Scan()
message := scanner.Text()
// TODO: messageでWelcomeHandlerを作成し、ServeHTTPを呼び出す
_ = message // 実装時にこの行を削除する
} else if handlerType == "method" {
// TODO: MethodHandlerを作成し、ServeHTTPを呼び出す
}
// レスポンスボディを出力する
fmt.Println(response.Body())
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー11標準ライブラリとOOP
io.Reader と io.Writersort.Interfacefmt.Stringer インターフェースencoding/json と構造体http.Handler インターフェースまとめ:REST API モデル自分で練習してみよう: Goオンラインコンパイラ