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で理解するミドルウェアとX-HTTP-Method-Overrideの実装🔄

Last updated at Posted at 2025-08-23

この記事で分かること

  • X-HTTP-Method-OverrideヘッダとはAPI側でGET,POST以外のメソッドをPOSTを使って表現することを許可するのを可能にするヘッダのこと
  • ミドルウェアはデコレーターパターンによりリクエストオブジェクトを上書きすることができる
  • 例えばミドルウェアでX-HTTP-Method-Overrideヘッダーからメソッドを上書きすることができる
  • Go系のフレームワークでX-HTTP-Method-Overrideヘッダーを扱うには自前でミドルウェアを実装する必要がある
  • JavaScript系だとExpress、PHP系だとslimX-HTTP-Method-Overrideヘッダーを扱うミドルウェアを提供している

LT版はこちらです

背景 🖼️

X-HTTP-Method-Overrideヘッダを以下の本を読んで知りました。

サーバー側のフレームワークやミドルウェアがこのヘッダをサポートして自動で解釈してくれる場合も多い

このような記載がありましたのでどんなフレームワークやミドルウェアがこれに対応しているのか調査します。
また、業務ではバックエンドでGoを使っているのでGoのビルトインではどんな記述をする必要があるのか実際にコードを書いて試します。

X-HTTP-Method-Overrideヘッダとは 💡

API側でGET,POST以外のメソッドをPOSTを使って表現することを許可するのを可能にするヘッダです。

例えばHTMLのForm経由だとメソッドにはGET,POST`しか指定できず、PATCH,DELETE,PUTはサポートされていないです。

参考
https://blog.jxck.io/entries/2023-11-27/hixie.html

他の手段として_methodパラメータを使う方法もありますがこちらは今回触れません。

X-HTTP-Method-OverrideヘッダーからMethodを上書きする機能を持つフレームワークやミドルウェア 🔍

ミドルウェアとは 🔄

そもそもミドルウェアについてわかっていないので調べます。

The way this works is that middleware implements a decorator pattern: it takes the request, does something, and returns another request object to the next layer of the stack.

image.png

ミドルウェアは以下の役割を持つことがわかります。
リクエストを受け取り、何らかの処理を行い、次の層に別のリクエストオブジェクトを返す

今回のメソッドの上書きはミドルウェアで行われるので以下のようなイメージです。

image.png

参考

実装:Goでミドルウェアを実装しX-HTTP-Method-Overrideからメソッドを上書きする 🏃‍♀️

以下のリポジトリが完成版です。
go-blueprintでテンプレートを作成しました。
https://github.com/yamatai12/sample-x-http-method-override

internal/server/routes.go
package server

import (
	"encoding/json"
	"log"
	"net/http"
)

func (s *Server) RegisterRoutes() http.Handler {
	mux := http.NewServeMux()

	// Register routes
	mux.HandleFunc("/", s.HelloWorldHandler)

	return mux
}

func (s *Server) HelloWorldHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Method:", r.Method)
	resp := map[string]string{"message": "Hello World"}
	jsonResp, err := json.Marshal(resp)
	if err != nil {
		http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	if _, err := w.Write(jsonResp); err != nil {
		log.Printf("Failed to write response: %v", err)
	}
}

以下の関数を実装します。

func (s *Server) methodOverrideMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			if override := r.Header.Get("X-HTTP-Method-Override"); override != "" {
				r.Method = override
			}
		}
		next.ServeHTTP(w, r)
	})
}

そして、RegisterRoutesのmuxをこの関数でラップします。

func (s *Server) RegisterRoutes() http.Handler {
	mux := http.NewServeMux()

	// Register routes
	mux.HandleFunc("/", s.HelloWorldHandler)

	// Wrap the mux with middleware
	return s.methodOverrideMiddleware(mux)
}

ミドルウェアはデコレーターパターンで実装しているということについて

デコレーターパターンとは

  • 関数を別の関数でラップすることで、その関数の機能を変更できるデザインパターンのこと
  • 元となるオブジェクトにどんどんデコレート(装飾)を行うことで機能の拡張を行うようなパターンのこと

methodOverrideMiddlewareは、引数として受け取ったnext http.Handlerをラップし、新しいhttp.Handlerを返しています。

参考

検証;X-HTTP-Method-Overrideからメソッドを上書きする ✅

curlで以下のリクエストを送ります。

curl -X POST localhost:8080 -H "X-HTTP-Method-Override: PUT"

X-HTTP-Method-OverrideヘッダでPUTを指定すると、API側でPUTメソッドとして解釈されるのか確認します。

HelloWorldHandler内にlogでメソッドを表示するようにしました。確認すると以下が表示されました。

Method: PUT

これでリクエストを送るとMethodがPOSTからPUTに変換されたとわかります。

今後調べたいこと 💪

  • HTTPメソッドをPost,Getメソッドでしかクライアント側で指定できないことがあるケースについて
  • HTMLのForm経由だとメソッドにはGET,POST`しか指定できない理由について

最後に

以下を理解できました

  • ミドルウェアの概念
  • Go系だとX-HTTP-Method-Overrideヘッダーによるメソッドの上書きは自前で実装する必要があること
  • 言語によってはフレームワーク側でX-HTTP-Method-Overrideヘッダーによるメソッドの上書きを提供するミドルウェアが用意されているということ

参考✨

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?