devlog

echo の Middleware でレスポンスボディを加工する[雑記]

2024-02-21

概要

  • echo は Go のウェブフレームワーク
  • echo の Middleware でレスポンスボディを加工する方法を検討した
  • c.Set() を使う方法を紹介する
  • 他に Context 自体をカスタマイズする方法や c.Response().Writer を使う方法がある

レスポンスボディを加工したい

echo で次のようなコードを記述した。
Middleware でレスポンスボディ (ApiResponse) を加工したい。

package main import ( "github.com/labstack/echo/v4" ) type ApiResponse struct { Data interface{} `json:"data"` } func main() { app := echo.New() // ミドルウェアでレスポンスボディを加工したい // app.Use(SomethingMiddleware) // ハンドラー app.GET("/api/hello", func(c echo.Context) error { // このレスポンスをミドルウェアで加工したい res := ApiResponse { Data: struct{}{}, } return c.JSON(200, res) }) app.Start(":3000") }

だがレスポンスボディを気軽にぱっと get / set する方法が無さそう。
c.Response().Writer を使う方法は見つけたが、手がかかりそうな印象。

そのため別の方法を検討した。

c.Set() でデータをセットする

c.Set() でデータをセットして c.Get() でデータを取得できる

// データをセット c.Set("data", data)

この c.Set() を使えばミドルウェアへデータを渡せそう。
これを活用して最終的に次のように実装した。

最終的なコード

変更内容

  • Handler で c.JSON() を呼ばない
  • 代わりに c.Set() でデータをセットする
  • Middleware でデータを取り出し加工、、最後に c.JSON() でレスポンスを返す
package main import ( "github.com/labstack/echo/v4" ) type ApiResponse struct { Data interface{} `json:"data"` } // データをセット func WithData(c echo.Context, data interface{}) error { c.Set("data", data) return nil } // ミドルウェア func HandleData(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { // ハンドラーを実行 err := next(c) if err != nil { return err } // データを取り出す data := c.Get("data") if data == nil { data = struct{}{} } // レスポンスを返す res := ApiResponse { Data: data, } return c.JSON(200, res) } } func main() { app := echo.New() // ミドルウェア app.Use(HandleData) // ハンドラー app.GET("/api/hello", func(c echo.Context) error { return WithData(c, struct{}{}) }) app.Start(":3000") }

終わりに

API全体で共通のフィールドがあるとき、上記の機構が便利かもです。

  • 作成日
    2024-02-21
  • 更新日
    2024-02-21