package server import ( "container/list" "encoding/json" "net/http" "reflect" "strings" "git.pyer.club/kingecg/gohttpd/model" ) type Middleware func(w http.ResponseWriter, r *http.Request, next func()) type MiddlewareLink struct { *list.List } func IsEqualMiddleware(a, b Middleware) bool { if a == nil && b == nil { return true } if a == nil || b == nil { return false } return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() } func (ml *MiddlewareLink) Add(m Middleware) { if m == nil { return } if ml.List.Len() == 0 { ml.PushBack(m) } else { if IsEqualMiddleware(m, Done) { return } el := ml.Back() ml.InsertBefore(m, el) } } func (ml *MiddlewareLink) ServeHTTP(w http.ResponseWriter, r *http.Request) bool { canContinue := true next := func() { canContinue = true } for e := ml.Front(); e != nil && canContinue; e = e.Next() { canContinue = false e.Value.(Middleware)(w, r, next) if !canContinue { break } } return canContinue } func NewMiddlewareLink() *MiddlewareLink { ml := &MiddlewareLink{list.New()} ml.Add(Done) return ml } func BasicAuth(w http.ResponseWriter, r *http.Request, next func()) { config := model.GetConfig() if config.Admin.Username == "" || config.Admin.Password == "" { next() return } user, pass, ok := r.BasicAuth() if ok && user == config.Admin.Username && pass == config.Admin.Password { next() } else { w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) http.Error(w, "Unauthorized.", http.StatusUnauthorized) } } func Parse[T any](w http.ResponseWriter, r *http.Request, next func()) { if r.Method == "POST" || r.Method == "PUT" { //判断r的content-type是否是application/x-www-form-urlencoded if r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" { r.ParseForm() next() return } if r.Header.Get("Content-Type") == "multipart/form-data" { r.ParseMultipartForm(r.ContentLength) next() return } // 判断r的content-type是否是application/json contentType := r.Header.Get("Content-Type") if strings.Contains(contentType, "application/json") { var t T // 读取json数据 if err := json.NewDecoder(r.Body).Decode(&t); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } ctx := r.Context() m := ctx.Value(RequestCtxKey("data")).(map[string]interface{}) if m != nil { m["data"] = t } next() return } } next() } func Done(w http.ResponseWriter, r *http.Request, next func()) { next() }