💌

GoでのMiddlewareの役割と実装方法についてまとめ

に公開

はじめに

Middlewareは、HTTPリクエストとレスポンスの処理をフック(hook)し、共通の処理を適用するための仕組みのことです。
Goでは、主にnet/httpパッケージを使用して簡単にMiddlewareを実装することができます。

今回はMiddlewareの基本概念、Goにおける実装方法と活用例を簡単にまとめました。

対象読者

  • GoのMiddlewareの基本を学びたい方
  • 共通の処理を効率的に適用する方法を知りたい方
  • 実践的なMiddlewareの書き方を学びたい方

目次

  1. Middlewarrとは?
    • Middlewareの役割
    • Middlewareを使うメリット
  2. GoでのMiddlewareの基本
    • Goのnet/httpを使ったMiddleware
    • シンプルなMiddlewareの実装
  3. 実践的なMiddlewareの例
    • ロギングMiddleware
    • 認証Middleware
    • CORS Middleware
  4. まとめ

1. Middlewareとは?

1.1 Middlewareの役割

Middlewareは、HTTPリクエストを処理する前後で特定の処理を実行する仕組みです。
例えば、以下のような処理をMiddlewareで実装できます。

役割 説明
ロギング リクエストの情報を記録する
認証 ユーザーの認証を行う
CORS対応 クロスオリジンリクエストを許可する
リクエストバリデーション リクエストデータの検証を行う

1.2 Middlewareを使うメリット

Middlewareを導入することで、以下のような開発効率の向上が期待できます。

  • 共通処理を一箇所にまとめられる → コードの重複を削減
  • リクエストの前処理・後処理が簡単にできる
  • 複数のMiddlewareを組み合わせて柔軟な制御が可能

2. GoでのMiddlewareの基本

2.1 Goのnet/httpを使ったMiddleware

Goでは、http.Handlerをラップする関数を使ってMiddlewareを実装できます。

Middlewareの基本構造

package main

import (
    "fmt"
    "net/http"
)

// Middlewareの定義
func middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Middleware: リクエストを処理中...")
        next.ServeHTTP(w, r)
        fmt.Println("Middleware: レスポンスを返しました。")
    })
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello, World!")
}

func main() {
    http.Handle("/", middleware(http.HandlerFunc(handler)))
    http.ListenAndServe(":8080", nil)
}

2.2 シンプルなMiddlewareの実装

このMiddlewareは、リクエストが処理される前後にメッセージを出力します。

  • middleware()http.Handlerを受け取り、新しい http.Handlerを返す
  • next.ServeHTTP(w, r)を実行することで、次の処理(エンドポイントのハンドラー)を呼び出す

実行すると、リクエストごとにリクエストの前後でログが表示されます。


3. 実践的なMiddlewareの例

3.1 ロギングMiddleware

リクエストの URL・メソッド・処理時間を記録するMiddleware。

package main

import (
    "log"
    "net/http"
    "time"
)

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        duration := time.Since(start)
        log.Printf("%s %s %v", r.Method, r.URL.Path, duration)
    })
}

3.2 認証Middleware(JWT)

JWT(JSON Web Token)を使った認証 Middlewareの例。

package main

import (
    "net/http"
)

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        if token != "valid-token" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}
  • Authorizationヘッダーに"valid-token"が含まれている場合のみ許可
  • 不正なリクエストは401 Unauthorizedを返す

3.3 CORS Middleware

フロントエンド(ReactやVueなど)と連携する際に、CORSを許可する Middleware。

package main

import "net/http"

func corsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        if r.Method == "OPTIONS" {
            w.WriteHeader(http.StatusOK)
            return
        }
        next.ServeHTTP(w, r)
    })
}
  • すべてのオリジン(*)を許可
  • OPTIONSリクエストに200 OKを返すことで、プリフライトリクエストを処理

4. まとめ

項目 説明
Middlewareの役割 共通処理(ロギング、認証、CORSなど)を適用する
GoでのMiddlewareの書き方 http.Handlerをラップする関数を作成
実践的なMiddleware ロギング・認証・CORSなどの Middlewareを実装

Middlewareを組み合わせてAPIの拡張性を向上させることもできたりします。
フロントエンドと連携するようなWebアプリケーションを作成するときには恐らく触れる概念だと思うので、是非検証してみてください!

Discussion