五步用golang封装自己web框架httper:第五步,实现http.handler接口

我们知道,实现一个接口所有方法,就是该接口
golang内置库http内http.HandlerFunc就是http.Handler接口的一种实现,为此我们可以用以下方法实现http.Handler接口

  • ContextHandle
  • ErrorHandle
  • ResultHandle
    读者可以对比测试文件,使用符合自己使用习惯的实现

ContextHandle,类似gin

该实现只封装http.ResponseWriter,*http.Request

handle/context.go

type ContextHandle func(c httper.Context)

func (ch ContextHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    c := httper.NewContext(w, r) ch(c)
}

ErrorHandle,统一错误处理,类似echo

handle/error.go

type ErrorHandle func(c httper.Context) error

func (eh ErrorHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 c := httper.NewContext(w, r) err := eh(c) UnitErrorHandle(c, err)}

var UnitErrorHandle = func(c httper.Context, err error) {
    if err == nil {
        return
    }
    http.Error(c.Writer(), err.Error(), http.StatusInternalServerError)
}

ResultHandle,统一结果处理,类似node.js的express

篇幅关系,result接口及其实现不在此处赘述。详细请看 Golang接口?类型!

handle/result.go

type ResultHandle func(c httper.Context) result.Result

func (rh ResultHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    c := httper.NewContext(w, r)
    rs := rh(c)
    UnitResultHandle(c, rs)
}

var UnitResultHandle = func(c httper.Context, rs result.Result) {
    if rs == nil {
        return
    }
    status := http.StatusOK
    m := make(map[string]any)
    if rs.Error() != nil || rs.Code() != result.Success {
        status = http.StatusInternalServerError
        m["error"] = rs.Error().Error()
    }
    if msg := result.MapCodeMessage[rs.Code()]; msg != "" {
        m["message"] = msg
    }
    if rs.Data() != nil {
        m["data"] = rs.Data()
    }
    m["code"] = rs.Code()
    err := c.JSON(status, m)
    if err != nil {
        http.Error(c.Writer(), err.Error(), http.StatusInternalServerError)
    }
}

测试

func TestHandle(t *testing.T) {
    data := struct {
        Hello string `json:"hello"`
    }{
        Hello: "world",
    }
    mux := httper.New()
    mux.POST("/context", handle.ContextHandle(func(c httper.Context) {
        err := c.BindJson(&data)
        if err != nil {
            _ = c.Error(http.StatusBadRequest, err)
            return
        }
        err = c.JSON(http.StatusOK, data)
        if err != nil {
            _ = c.Error(http.StatusInternalServerError, err)
            return
        }
    }))
    mux.POST("/error", handle.ErrorHandle(func(c httper.Context) error {
        err := c.BindJson(&data)
        if err != nil {
            return c.Error(http.StatusBadRequest, err)
        }
        return c.JSON(http.StatusOK, data)
    }))
    mux.POST("/result", handle.ResultHandle(func(c httper.Context) result.Result {
        err := c.BindJson(&data)
        if err != nil {
            return result.ErrBadRequest.With(err)
        }
        return result.Map{
            "hello": data.Hello,
        }
    }))

    for r, f := range mux.Routes() {
        t.Log("register router:", r, f)
    }
    t.Fatal(mux.Start(":8000"))
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!