From 79e94dfd21a19e6608de765a5b43aaff212f0ee1 Mon Sep 17 00:00:00 2001 From: loveuer Date: Mon, 29 Jan 2024 15:48:09 +0800 Subject: [PATCH] feat: add nft(nf_util) package: resp(wrap status, data, msg ...); add config: enable_not_impled_handler(default return 501 not impled) --- group.go | 21 ++++++- handler.go | 6 ++ nf.go | 3 +- nft/resp/error.go | 70 +++++++++++++++++++++++ nft/resp/resp.go | 127 +++++++++++++++++++++++++++++++++++++++++ nft/resp/var.go | 17 ++++++ util.go | 12 ---- xtest/basic/basic.http | 6 +- xtest/basic/main.go | 8 ++- 9 files changed, 254 insertions(+), 16 deletions(-) create mode 100644 nft/resp/error.go create mode 100644 nft/resp/resp.go create mode 100644 nft/resp/var.go diff --git a/group.go b/group.go index 2facd20..84e8f1b 100644 --- a/group.go +++ b/group.go @@ -1,6 +1,7 @@ package nf import ( + "fmt" "log" "net/http" ) @@ -25,8 +26,26 @@ func (group *RouterGroup) Group(prefix string) *RouterGroup { return newGroup } +func (group *RouterGroup) verifyHandlers(path string, handlers ...HandlerFunc) []HandlerFunc { + if len(handlers) == 0 { + if !group.app.config.EnableNotImplementHandler { + panic(fmt.Sprintf("missing handler in route: %s", path)) + } + + handlers = append(handlers, ToDoHandler) + } + + for _, handler := range handlers { + if handler == nil { + panic(fmt.Sprintf("nil handler found in route: %s", path)) + } + } + + return handlers +} + func (group *RouterGroup) addRoute(method string, comp string, handlers ...HandlerFunc) { - verifyHandlers(comp, handlers...) + handlers = group.verifyHandlers(comp, handlers...) pattern := group.prefix + comp log.Printf("Add Route %4s - %s", method, pattern) group.app.router.addRoute(method, pattern, handlers...) diff --git a/handler.go b/handler.go index 64f3a2a..7a6a060 100644 --- a/handler.go +++ b/handler.go @@ -1,3 +1,9 @@ package nf +import "fmt" + type HandlerFunc func(*Ctx) error + +func ToDoHandler(c *Ctx) error { + return c.Status(501).SendString(fmt.Sprintf("%s - %s Not Implemented", c.Method, c.Path())) +} diff --git a/nf.go b/nf.go index 5285476..d8b94f4 100644 --- a/nf.go +++ b/nf.go @@ -19,7 +19,8 @@ type Config struct { DisableRecover bool `json:"-"` DisableHttpErrorLog bool `json:"-"` - NotFoundHandler HandlerFunc `json:"-"` + EnableNotImplementHandler bool `json:"-"` + NotFoundHandler HandlerFunc `json:"-"` } var ( diff --git a/nft/resp/error.go b/nft/resp/error.go new file mode 100644 index 0000000..b306f93 --- /dev/null +++ b/nft/resp/error.go @@ -0,0 +1,70 @@ +package resp + +import ( + "errors" + "fmt" + "github.com/loveuer/nf" +) + +type Error struct { + status uint32 + msg string + err error + data any +} + +func (e Error) Error() string { + if e.msg != "" { + return fmt.Sprintf("%s: %s", e.msg, e.err.Error()) + } + + switch e.status { + case 200: + return fmt.Sprintf("%s: %s", MSG200, e.err.Error()) + case 202: + return fmt.Sprintf("%s: %s", MSG202, e.err.Error()) + case 400: + return fmt.Sprintf("%s: %s", MSG400, e.err.Error()) + case 401: + return fmt.Sprintf("%s: %s", MSG401, e.err.Error()) + case 403: + return fmt.Sprintf("%s: %s", MSG403, e.err.Error()) + case 404: + return fmt.Sprintf("%s: %s", MSG404, e.err.Error()) + case 429: + return fmt.Sprintf("%s: %s", MSG429, e.err.Error()) + case 500: + return fmt.Sprintf("%s: %s", MSG500, e.err.Error()) + case 501: + return fmt.Sprintf("%s: %s", MSG501, e.err.Error()) + } + + return e.err.Error() + +} + +func NewError(statusCode uint32, msg string, rawErr error, data any) Error { + return Error{ + status: statusCode, + msg: msg, + err: rawErr, + data: data, + } +} + +func RespError(c *nf.Ctx, err error) error { + if err == nil { + return Resp(c, 500, MSG500, "response with nil error", nil) + } + + var re = &Error{} + if errors.As(err, re) { + if re.err == nil { + return Resp(c, re.status, re.msg, re.msg, re.data) + } + + return Resp(c, re.status, re.msg, re.err.Error(), re.data) + } + + return Resp(c, 500, MSG500, err.Error(), nil) +} diff --git a/nft/resp/resp.go b/nft/resp/resp.go new file mode 100644 index 0000000..1ef328d --- /dev/null +++ b/nft/resp/resp.go @@ -0,0 +1,127 @@ +package resp + +import ( + "fmt" + "github.com/loveuer/nf" + "strconv" + "strings" +) + +func handleEmptyMsg(status uint32, msg string) string { + if msg == "" { + switch status { + case 200: + msg = MSG200 + case 202: + msg = MSG202 + case 400: + msg = MSG400 + case 401: + msg = MSG401 + case 403: + msg = MSG403 + case 404: + msg = MSG404 + case 429: + msg = MSG429 + case 500: + msg = MSG500 + case 501: + msg = MSG501 + } + } + + return msg +} + +func Resp(c *nf.Ctx, status uint32, msg string, err string, data any) error { + msg = handleEmptyMsg(status, msg) + + c.Set(RealStatusHeader, strconv.Itoa(int(status))) + + if data == nil { + return c.JSON(nf.Map{"status": status, "msg": msg, "err": err}) + } + + return c.JSON(nf.Map{"status": status, "msg": msg, "err": err, "data": data}) +} + +func Resp200(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG200 + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + } + + return Resp(c, 200, msg, "", data) +} + +func Resp202(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG202 + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + } + + return Resp(c, 202, msg, "", data) +} + +func Resp400(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG400 + err := "" + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + err = msg + } + + return Resp(c, 400, msg, err, data) +} + +func Resp401(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG401 + err := "" + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + err = msg + } + + return Resp(c, 401, msg, err, data) +} + +func Resp403(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG403 + err := "" + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + err = msg + } + + return Resp(c, 403, msg, err, data) +} + +func Resp429(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG429 + err := "" + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + err = "" + } + + return Resp(c, 429, msg, err, data) +} + +func Resp500(c *nf.Ctx, data any, msgs ...string) error { + msg := MSG500 + err := "" + + if len(msgs) > 0 && msgs[0] != "" { + msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; ")) + err = msg + } + + return Resp(c, 500, msg, err, data) +} diff --git a/nft/resp/var.go b/nft/resp/var.go new file mode 100644 index 0000000..067939e --- /dev/null +++ b/nft/resp/var.go @@ -0,0 +1,17 @@ +package resp + +const ( + MSG200 = "请求成功" + MSG202 = "请求成功, 请稍后..." + MSG400 = "请求参数错误" + MSG401 = "登录已过期, 请重新登录" + MSG403 = "请求权限不足" + MSG404 = "请求资源未找到" + MSG429 = "请求过于频繁, 请稍后再试" + MSG500 = "服务器开小差了, 请稍后再试" + MSG501 = "功能开发中, 尽情期待" +) + +const ( + RealStatusHeader = "NF-STATUS" +) diff --git a/util.go b/util.go index 5fdc6a1..fce18ca 100644 --- a/util.go +++ b/util.go @@ -27,18 +27,6 @@ const ( MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=utf-8" ) -func verifyHandlers(path string, handlers ...HandlerFunc) { - if len(handlers) == 0 { - panic(fmt.Sprintf("missing handler in route: %s", path)) - } - - for _, handler := range handlers { - if handler == nil { - panic(fmt.Sprintf("nil handler found in route: %s", path)) - } - } -} - // parseVendorSpecificContentType check if content type is vendor specific and // if it is parsable to any known types. If it's not vendor specific then returns // the original content type. diff --git a/xtest/basic/basic.http b/xtest/basic/basic.http index daff45c..881d4c1 100644 --- a/xtest/basic/basic.http +++ b/xtest/basic/basic.http @@ -1,2 +1,6 @@ ### basic - get -GET http://127.0.0.1/hello/nf \ No newline at end of file +GET http://127.0.0.1/hello/nf + + +### test resp error +GET http://127.0.0.1/error \ No newline at end of file diff --git a/xtest/basic/main.go b/xtest/basic/main.go index 252d6f5..df46304 100644 --- a/xtest/basic/main.go +++ b/xtest/basic/main.go @@ -1,24 +1,30 @@ package main import ( + "errors" "github.com/loveuer/nf" + "github.com/loveuer/nf/nft/resp" "log" "net" "time" ) func main() { - app := nf.New() + app := nf.New(nf.Config{EnableNotImplementHandler: true}) app.Get("/hello/:name", func(c *nf.Ctx) error { name := c.Param("name") return c.JSON(nf.Map{"status": 200, "data": "hello, " + name}) }) + app.Get("/not_impl") app.Patch("/world", func(c *nf.Ctx) error { time.Sleep(5 * time.Second) c.Status(404) return c.JSON(nf.Map{"method": c.Method, "status": c.StatusCode}) }) + app.Get("/error", func(c *nf.Ctx) error { + return resp.RespError(c, resp.NewError(404, "not found", errors.New("NNNot Found"), nil)) + }) ln, _ := net.Listen("tcp", ":80") log.Fatal(app.RunListener(ln))