0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

はじめに

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アプリケーションを作成するときには恐らく触れる概念だと思うので、是非検証してみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?