怎么使用中间件

怎么使用中间件

假设我们做一个需要登录的 app,在浏览器访问任意页面,需要先鉴权,鉴权失败则重定向到登录页面。显然这里用中间件较好。

Egine 结构的 Mount、Handle 和 HandleFunc 方法均支持中间件,函数签名如下:

func (e *Engine) Mount(path string, component any, middlewares ...func(http.Handler) http.Handler) *Engine
func (e *Engine) Handle(path string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) *Engine
func (e *Engine) HandleFunc(path string, handler http.HandlerFunc, middlewares ...func(http.Handler) http.Handler) *Engine

一个简单的 demo 代码如下:

package main

import (
	"fmt"
	"math/rand"
	"net/http"

	"github.com/zrcoder/amisgo"
	"github.com/zrcoder/amisgo/comp"
	"github.com/zrcoder/amisgo/model"
	"github.com/zrcoder/amisgo/util"
)

const (
	loginUrl   = "/login"
	echoApiUrl = "/api/echo"
)

func main() {
	index := comp.Page().InitApi(echoApiUrl).Body("${body}")
	login := comp.Page().Body(
		comp.Form().Body(
			comp.InputEmail().Name("user"),
			comp.InputPassword().Name("password"),
		),
	)
	app := amisgo.New().
		Mount("/", index, checkAuthMiddleware, testMiddleware).
		Mount(loginUrl, login).
		HandleFunc(echoApiUrl, echo)

	panic(app.Run(":8080"))
}

func checkAuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Pre-processing actions, such as logging access, authentication, etc.
		fmt.Println("check auth middleware")
		if r.URL.Path != loginUrl && !checkAuth(r) {
			util.Redirect(w, r, loginUrl, http.StatusTemporaryRedirect)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func testMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("test middleware")
		w.Header().Set("test", "test heander value")
		next.ServeHTTP(w, r)
		// Post-processing actions, such as logging debug information
		fmt.Println("response heander for [test]:", w.Header().Get("test"))
	})
}

func echo(w http.ResponseWriter, r *http.Request) {
	resp := model.SuccessResponse("", model.Data{"body": "Hello, amisgo!"})
	w.Write(resp.Json())
}

func checkAuth(r *http.Request) bool {
	// Parse the token from the request and process authentication.
	// This is just a demonstration; it randomly returns the authentication result.
	return rand.Intn(2) == 0
}