Menu
Coddy logo textTech

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 パターンを実現できます。

challenge icon

チャレンジ

簡単

Web リクエストがどのように処理されるかをシミュレートする、シンプルな HTTP handler system を構築しましょう!この環境では実際の HTTP サーバーを実行できないため、http.Handler interface を implement する handlers を作成し、モックの request/response オブジェクトを使ってそれらがどのようにリクエストを処理するかを示します。

コードを 2 つのファイルに整理します。

  • handlers.go: カスタム HTTP handlers を定義します。

    HTTP response に書き込まれる内容を captures する MockResponseWriter struct を Create します。response body を string として保存し、data を body に appends する Write(data []byte) (int, error) method を implement する必要があります。accumulated response を取得するための Body() string method も Add します。

    HTTP request をシミュレートするため、PathMethod の string field を持つ MockRequest struct を Create します。

    次に、http.Handler interface pattern を implement する 2 つの handler struct を Create します(*MockResponseWriter*MockRequest を受け取る ServeHTTP method を持たせます)。

    • WelcomeHandlerMessage field を持つ)- 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 from

output は次のようになります。

Hello from /home

また、次の入力が与えられた場合:

method
/api/users
POST

output は次のようになります。

Creating resource

さらに、次の入力が与えられた場合:

method
/api/data
GET

output は次のようになります。

Fetching data

さらに、次の入力が与えられた場合:

method
/api/items
DELETE

output は次のようになります。

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())
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Goオンラインコンパイラ