feat: add nft(nf_util) package: resp(wrap status, data, msg ...); add config: enable_not_impled_handler(default return 501 not impled)
This commit is contained in:
		
							
								
								
									
										21
									
								
								group.go
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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...)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								nf.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								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 (
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								nft/resp/error.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								nft/resp/error.go
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										127
									
								
								nft/resp/resp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								nft/resp/resp.go
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								nft/resp/var.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								nft/resp/var.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package resp
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MSG200 = "请求成功"
 | 
			
		||||
	MSG202 = "请求成功, 请稍后..."
 | 
			
		||||
	MSG400 = "请求参数错误"
 | 
			
		||||
	MSG401 = "登录已过期, 请重新登录"
 | 
			
		||||
	MSG403 = "请求权限不足"
 | 
			
		||||
	MSG404 = "请求资源未找到"
 | 
			
		||||
	MSG429 = "请求过于频繁, 请稍后再试"
 | 
			
		||||
	MSG500 = "服务器开小差了, 请稍后再试"
 | 
			
		||||
	MSG501 = "功能开发中, 尽情期待"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	RealStatusHeader = "NF-STATUS"
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										12
									
								
								util.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,6 @@
 | 
			
		||||
### basic - get
 | 
			
		||||
GET http://127.0.0.1/hello/nf
 | 
			
		||||
GET http://127.0.0.1/hello/nf
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### test resp error
 | 
			
		||||
GET http://127.0.0.1/error
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user