Zenn
Closed8

Go net/httpの使い方

komugi8komugi8

net/httpパッケージはクライアントとサーバ側の両方の機能を提供している.一旦,サーバ側の理解を深める.流れとしては,クライアントマルチプレクサハンドラのようなイメージを持っておくと良さそう.マルチプレクサとハンドラはどちらもサーバ側の話である.net/httpパッケージはマルチプレクサのインターフェースに加え,デフォルトで使用されるマルチプレクサも提供している.
サーバーを建てる際には,ListenAndServeを使用すればよく,第一引数にネットワークアドレスを,第二引数にリクエストを処理するハンドラを使用すれば良い.ネットワークアドレスが空の場合,ポート80が設定され,ハンドラがnilの場合,デフォルトのマルチプレクサDefaultServerMux(URLに応じてリクエストを各ハンドラに転送する特殊なハンドラ)が使用される.(ハンドラについては後のコメントで書く.)

komugi8komugi8

Server構造体を使用することでサーバの設定を行える.

type Server struct {
	Addr string
	Handler Handler
	DisableGeneralOptionsHandler bool
	TLSConfig *tls.Config
	ReadTimeout time.Duration
	ReadHeaderTimeout time.Duration
	WriteTimeout time.Duration
	IdleTimeout time.Duration
	MaxHeaderBytes int
	TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
	ConnState func(net.Conn, ConnState)
	ErrorLog *log.Logger
	BaseContext func(net.Listener) context.Context
	ConnContext func(ctx context.Context, c net.Conn) context.Context
	HTTP2 *HTTP2Config
	Protocols *Protocols
}
komugi8komugi8
package main

import (
  "net/http"
)

func main() {
  http.ListenAndServe("", nil)
}

上記コードをServer構造体を使用して設定してみると以下のようにかける.
サーバに追加の設定が必要な際は適宜追加すると良さそう.

package main

import (
  "net/http"
)

func main() {
  server := http.Server{
    Addr: "127.0.0.1:80",
    Handler: nil,
  }
  server.ListenAndServe()
}
komugi8komugi8

サーバーに機能を持たせるためにハンドラが必要.GolangにおけるハンドラはServeHTTPメソッドを持ったインターフェースである.

ServeHTTP(http.ResponseWriter, *http.Request)

ServeMuxDefaultServeMuxServeHTTPメソッドを持っているため,ListenAndServeのハンドラとして使用できている.

komugi8komugi8

ListenAndServeについて,ServeHTTPメソッドを持っているハンドラを第二引数に指定することができるので,マルチプレクサではないハンドラを登録することもできる.(ただし,URLのマッチング処理がないため,すべてのリクエストが同じハンドラに転送される.自分には使用場面がわからない)

komugi8komugi8

ServeHTTPメソッドを持つ構造体を作成して,複数のハンドラを登録してみる.http.Handle関数を使用することでハンドラをマルチプレクサに登録する.

package main

import (
	"net/http"
)

type HelloHandler struct {}

func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello, World!"))
}

type ByeHandler struct {}

func (h *ByeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Goodbye, World!"))
}

func main() {
	server := http.Server {
		Addr: ":8080",
	}

	helloHandler := HelloHandler{}
	http.Handle("/hello", &helloHandler)

	byeHandler := ByeHandler{}
	http.Handle("/bye", &byeHandler)

	server.ListenAndServe()
}
komugi8komugi8

Golangにはハンドル関数と呼ばれるものがある.ハンドラ関数はハンドラのメソッドであるServeHTTPと同じようなシグネチャを持つ関数であり,ハンドラのように振る舞うことができる.ハンドラ関数を用いることで簡単にハンドラを登録することができる.

package main

import (
	"net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello, World!"))
}

func bye(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Goodbye, World!"))
}

func main() {
	server := http.Server {
		Addr: ":8080",
	}

	http.HandleFunc("/hello", hello)
	http.HandleFunc("/bye", bye)

	server.ListenAndServe()
}
komugi8komugi8

上記の例について,以下のリクエストを送ると404が返ってくる.

curl -X GET "http://localhost:8080/hello/ei"
404 page not found

では,以下のような変更を加えてみる.

+	http.HandleFunc("/hello/", hello)
-	http.HandleFunc("/hello", hello)

すると,結果は以下のようになる.

curl -X GET "http://localhost:8080/hello/ei"
Hello, World!

末尾が/ではないURLについて,ServeMuxは完全一致するものを探す.末尾が/である場合は,URLの前方一致するものを探す.そのため,URLをhelloからhello/にしたことで結果が変わった.

このスクラップは1ヶ月前にクローズされました
作成者以外のコメントは許可されていません