😺

http ServerでのBaseContextを調査

2023/12/23に公開

はじめに

この記事はGo 言語 Advent Calendar 202323日目の記事です。

今回はgoのnet/http ServerのBaseContextというフィールドの話をします。

BaseContextとは

  • net/httpServer には BaseContext というフィールドが存在します。
  • この BaseContext のデフォルトは context.Background() です。
// BaseContext optionally specifies a function that returns
// the base context for incoming requests on this server.
// The provided Listener is the specific Listener that's
// about to start accepting requests.
// If BaseContext is nil, the default is context.Background().
// If non-nil, it must return a non-nil context.
BaseContext func(net.Listener) context.Context

このフィールドに関数を登録すると、その関数によって提供される context.Context が返されます。例えば、特定の時間でタイムアウトさせたい場合は、ここで指定できます。

func(net.Listener) context.Context {
	ctx, _ := context.WithTimeout(ctx, 100*time.Millisecond)
	return ctx
}

Redditのこのスレッドで言及されていましたが、サーバーを立てる際に signal.NotifyContext を使用することがあります。これを BaseContext に渡すことで、シグナルを受け取った際にスムーズにキャンセルが伝播するのではないかと考え、試してみました。

実験

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
)

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	srv := &http.Server{
		Addr: ":8080",
		BaseContext: func(_ net.Listener) context.Context {
			return ctx
		},
	}

	http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
		select {
		case <-request.Context().Done():
			fmt.Fprintf(w, "cancel")
		}
		fmt.Fprintf(w, "Hello, World!")
	})

	go func() {
		if err := srv.ListenAndServe(); err != http.ErrServerClosed {
			log.Print(err)
		}
	}()

	<-ctx.Done()

	if err := srv.Shutdown(context.Background()); err != nil {
		log.Print(err)
	}
}
go build

別のコンソールからアクセスします。

curl http://localhost:8080/

ps コマンドでプロセスIDを見つけ、SIGINTを送信します。

ps aux | grep xxxxx
kill -SIGINT id

すると、curl を実行しているコンソールに以下が表示されます。

cancelHello, World!

これにより、キャンセルが適切に伝播していることが確認できます。

まとめ

  • net/http Server BaseContextフィールドを使用するとデフォルトのコンテキストを指定できる
  • signal.NotifyContextを使用するとシグナルからのキャンセルをハンドラーに伝播させるコトが出来る
  • 使いようによっては他にもつかえるので 便利な機能かも知れません

Discussion