improve package ghttp

This commit is contained in:
John Guo
2022-05-06 20:25:21 +08:00
parent ad04adccea
commit 25c091df7f
8 changed files with 51 additions and 61 deletions

View File

@ -25,19 +25,19 @@ import (
type (
// Server wraps the http.Server and provides more rich features.
Server struct {
instance string // Instance name.
config ServerConfig // Configuration.
plugins []Plugin // Plugin array to extend server functionality.
servers []*gracefulServer // Underlying http.Server array.
serverCount *gtype.Int // Underlying http.Server count.
closeChan chan struct{} // Used for underlying server closing event notification.
serveTree map[string]interface{} // The route maps tree.
serveCache *gcache.Cache // Server caches for internal usage.
routesMap map[string][]registeredRouteItem // Route map mainly for route dumps and repeated route checks.
statusHandlerMap map[string][]HandlerFunc // Custom status handler map.
sessionManager *gsession.Manager // Session manager.
openapi *goai.OpenApiV3 // The OpenApi specification management object.
service *gsvc.Service // The service for Registry.
instance string // Instance name of current HTTP server.
config ServerConfig // Server configuration.
plugins []Plugin // Plugin array to extend server functionality.
servers []*gracefulServer // Underlying http.Server array.
serverCount *gtype.Int // Underlying http.Server number for internal usage.
closeChan chan struct{} // Used for underlying server closing event notification.
serveTree map[string]interface{} // The route maps tree.
serveCache *gcache.Cache // Server caches for internal usage.
routesMap map[string][]*HandlerItem // Route map mainly for route dumps and repeated route checks.
statusHandlerMap map[string][]HandlerFunc // Custom status handler map.
sessionManager *gsession.Manager // Session manager.
openapi *goai.OpenApiV3 // The OpenApi specification management object.
service *gsvc.Service // The service for Registry.
}
// Router object.
@ -52,7 +52,7 @@ type (
// RouterItem is just for route dumps.
RouterItem struct {
Handler *handlerItem // The handler.
Handler *HandlerItem // The handler.
Server string // Server name.
Address string // Listening address.
Domain string // Bound domain.
@ -74,9 +74,9 @@ type (
Value reflect.Value // Reflect value information for current handler, which is used for extensions of the handler feature.
}
// handlerItem is the registered handler for route handling,
// HandlerItem is the registered handler for route handling,
// including middleware and hook functions.
handlerItem struct {
HandlerItem struct {
Id int // Unique handler item id mark.
Name string // Handler name, which is automatically retrieved from runtime stack when registered.
Type string // Handler type: object/handler/middleware/hook.
@ -91,16 +91,10 @@ type (
// handlerParsedItem is the item parsed from URL.Path.
handlerParsedItem struct {
Handler *handlerItem // Handler information.
Handler *HandlerItem // Handler information.
Values map[string]string // Router values parsed from URL.Path.
}
// registeredRouteItem stores the information of the router and is used for route map.
registeredRouteItem struct {
Source string // Source file path and its line number.
Handler *handlerItem // Handler object.
}
// Listening file descriptor mapping.
// The key is either "http" or "https" and the value is its FD.
listenerFdMap = map[string]string

View File

@ -104,7 +104,7 @@ func GetServer(name ...interface{}) *Server {
statusHandlerMap: make(map[string][]HandlerFunc),
serveTree: make(map[string]interface{}),
serveCache: gcache.New(),
routesMap: make(map[string][]registeredRouteItem),
routesMap: make(map[string][]*HandlerItem),
openapi: goai.New(),
}
// Initialize the server using default configurations.
@ -345,19 +345,19 @@ func (s *Server) GetRoutes() []RouterItem {
}
address += "tls" + s.config.HTTPSAddr
}
for k, registeredItems := range s.routesMap {
for k, handlerItems := range s.routesMap {
array, _ := gregex.MatchString(`(.*?)%([A-Z]+):(.+)@(.+)`, k)
for index, registeredItem := range registeredItems {
for index, handlerItem := range handlerItems {
item := RouterItem{
Server: s.config.Name,
Address: address,
Domain: array[4],
Type: registeredItem.Handler.Type,
Type: handlerItem.Type,
Middleware: array[1],
Method: array[2],
Route: array[3],
Priority: len(registeredItems) - index - 1,
Handler: registeredItem.Handler,
Priority: len(handlerItems) - index - 1,
Handler: handlerItem,
}
switch item.Handler.Type {
case HandlerTypeObject, HandlerTypeHandler:

View File

@ -70,7 +70,7 @@ func (s *Server) parsePattern(pattern string) (domain, method, path string, err
type setHandlerInput struct {
Prefix string
Pattern string
HandlerItem *handlerItem
HandlerItem *HandlerItem
}
// setHandler creates router item with a given handler and pattern and registers the handler to the router tree.
@ -131,11 +131,11 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
switch handler.Type {
case HandlerTypeHandler, HandlerTypeObject:
if items, ok := s.routesMap[routerKey]; ok {
var duplicatedHandler *handlerItem
for _, item := range items {
switch item.Handler.Type {
var duplicatedHandler *HandlerItem
for i, item := range items {
switch item.Type {
case HandlerTypeHandler, HandlerTypeObject:
duplicatedHandler = item.Handler
duplicatedHandler = items[i]
break
}
}
@ -225,11 +225,11 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
}
// It iterates the list array of `lists`, compares priorities and inserts the new router item in
// the proper position of each list. The priority of the list is ordered from high to low.
var item *handlerItem
var item *HandlerItem
for _, l := range lists {
pushed := false
for e := l.Front(); e != nil; e = e.Next() {
item = e.Value.(*handlerItem)
item = e.Value.(*HandlerItem)
// Checks the priority whether inserting the route item before current item,
// which means it has higher priority.
if s.compareRouterPriority(handler, item) {
@ -246,20 +246,16 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
}
// Initialize the route map item.
if _, ok := s.routesMap[routerKey]; !ok {
s.routesMap[routerKey] = make([]registeredRouteItem, 0)
s.routesMap[routerKey] = make([]*HandlerItem, 0)
}
var routeItem = registeredRouteItem{
Source: handler.Source,
Handler: handler,
}
switch handler.Type {
case HandlerTypeHandler, HandlerTypeObject:
// Overwrite the route.
s.routesMap[routerKey] = []registeredRouteItem{routeItem}
s.routesMap[routerKey] = []*HandlerItem{handler}
default:
// Append the route.
s.routesMap[routerKey] = append(s.routesMap[routerKey], routeItem)
s.routesMap[routerKey] = append(s.routesMap[routerKey], handler)
}
}
@ -271,7 +267,7 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
// 1. The middleware has the most high priority.
// 2. URI: The deeper, the higher (simply check the count of char '/' in the URI).
// 3. Route type: {xxx} > :xxx > *xxx.
func (s *Server) compareRouterPriority(newItem *handlerItem, oldItem *handlerItem) bool {
func (s *Server) compareRouterPriority(newItem *HandlerItem, oldItem *HandlerItem) bool {
// If they're all types of middleware, the priority is according to their registered sequence.
if newItem.Type == HandlerTypeMiddleware && oldItem.Type == HandlerTypeMiddleware {
return false

View File

@ -41,7 +41,7 @@ func (s *Server) doBindHookHandler(ctx context.Context, in doBindHookHandlerInpu
setHandlerInput{
Prefix: in.Prefix,
Pattern: in.Pattern,
HandlerItem: &handlerItem{
HandlerItem: &HandlerItem{
Type: HandlerTypeHook,
Name: gdebug.FuncPath(in.Handler),
Info: handlerFuncInfo{

View File

@ -30,7 +30,7 @@ func (s *Server) BindMiddleware(pattern string, handlers ...HandlerFunc) {
s.setHandler(ctx, setHandlerInput{
Prefix: "",
Pattern: pattern,
HandlerItem: &handlerItem{
HandlerItem: &HandlerItem{
Type: HandlerTypeMiddleware,
Name: gdebug.FuncPath(handler),
Info: handlerFuncInfo{
@ -53,7 +53,7 @@ func (s *Server) BindMiddlewareDefault(handlers ...HandlerFunc) {
s.setHandler(ctx, setHandlerInput{
Prefix: "",
Pattern: defaultMiddlewarePattern,
HandlerItem: &handlerItem{
HandlerItem: &HandlerItem{
Type: HandlerTypeMiddleware,
Name: gdebug.FuncPath(handler),
Info: handlerFuncInfo{

View File

@ -56,8 +56,8 @@ func (s *Server) getHandlersWithCache(r *Request) (parsedItems []*handlerParsedI
if xUrlPath := r.Header.Get(HeaderXUrlPath); xUrlPath != "" {
path = xUrlPath
}
var handlerKey = s.serveHandlerKey(method, path, host)
value, err := s.serveCache.GetOrSetFunc(ctx, handlerKey, func(ctx context.Context) (interface{}, error) {
var handlerCacheKey = s.serveHandlerKey(method, path, host)
value, err := s.serveCache.GetOrSetFunc(ctx, handlerCacheKey, func(ctx context.Context) (interface{}, error) {
parsedItems, hasHook, hasServe = s.searchHandlers(method, path, host)
if parsedItems != nil {
return &handlerCacheItem{parsedItems, hasHook, hasServe}, nil
@ -152,7 +152,7 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
// As the tail of the list array has the most priority, it iterates the list array from its tail to head.
for i := len(lists) - 1; i >= 0; i-- {
for e := lists[i].Front(); e != nil; e = e.Next() {
item := e.Value.(*handlerItem)
item := e.Value.(*HandlerItem)
// Filter repeated handler items, especially the middleware and hook handlers.
// It is necessary, do not remove this checks logic unless you really know how it is necessary.
if _, ok := repeatHandlerCheckMap[item.Id]; ok {
@ -212,7 +212,7 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
}
}
if parsedItemList.Len() > 0 {
index := 0
var index = 0
parsedItems = make([]*handlerParsedItem, parsedItemList.Len())
for e := parsedItemList.Front(); e != nil; e = e.Next() {
parsedItems[index] = e.Value.(*handlerParsedItem)
@ -223,7 +223,7 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (item handlerItem) MarshalJSON() ([]byte, error) {
func (item HandlerItem) MarshalJSON() ([]byte, error) {
switch item.Type {
case HandlerTypeHook:
return json.Marshal(

View File

@ -53,7 +53,7 @@ func (s *Server) doBindHandler(ctx context.Context, in doBindHandlerInput) {
s.setHandler(ctx, setHandlerInput{
Prefix: in.Prefix,
Pattern: in.Pattern,
HandlerItem: &handlerItem{
HandlerItem: &HandlerItem{
Type: HandlerTypeHandler,
Info: in.FuncInfo,
Middleware: in.Middleware,
@ -63,7 +63,7 @@ func (s *Server) doBindHandler(ctx context.Context, in doBindHandlerInput) {
}
// bindHandlerByMap registers handlers to server using map.
func (s *Server) bindHandlerByMap(ctx context.Context, prefix string, m map[string]*handlerItem) {
func (s *Server) bindHandlerByMap(ctx context.Context, prefix string, m map[string]*HandlerItem) {
for pattern, handler := range m {
s.setHandler(ctx, setHandlerInput{
Prefix: prefix,

View File

@ -92,7 +92,7 @@ func (s *Server) doBindObject(ctx context.Context, in doBindObjectInput) {
in.Pattern = s.serveHandlerKey("", path, domain)
}
var (
handlerMap = make(map[string]*handlerItem)
handlerMap = make(map[string]*HandlerItem)
reflectValue = reflect.ValueOf(in.Object)
reflectType = reflectValue.Type()
initFunc func(*Request)
@ -135,7 +135,7 @@ func (s *Server) doBindObject(ctx context.Context, in doBindObjectInput) {
}
key := s.mergeBuildInNameToPattern(in.Pattern, structName, methodName, true)
handlerMap[key] = &handlerItem{
handlerMap[key] = &HandlerItem{
Name: fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, methodName),
Type: HandlerTypeObject,
Info: funcInfo,
@ -162,7 +162,7 @@ func (s *Server) doBindObject(ctx context.Context, in doBindObjectInput) {
if len(k) == 0 || k[0] == '@' {
k = "/" + k
}
handlerMap[k] = &handlerItem{
handlerMap[k] = &HandlerItem{
Name: fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, methodName),
Type: HandlerTypeObject,
Info: funcInfo,
@ -187,7 +187,7 @@ type doBindObjectMethodInput struct {
func (s *Server) doBindObjectMethod(ctx context.Context, in doBindObjectMethodInput) {
var (
handlerMap = make(map[string]*handlerItem)
handlerMap = make(map[string]*HandlerItem)
reflectValue = reflect.ValueOf(in.Object)
reflectType = reflectValue.Type()
initFunc func(*Request)
@ -231,7 +231,7 @@ func (s *Server) doBindObjectMethod(ctx context.Context, in doBindObjectMethodIn
}
key := s.mergeBuildInNameToPattern(in.Pattern, structName, methodName, false)
handlerMap[key] = &handlerItem{
handlerMap[key] = &HandlerItem{
Name: fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, methodName),
Type: HandlerTypeObject,
Info: funcInfo,
@ -246,7 +246,7 @@ func (s *Server) doBindObjectMethod(ctx context.Context, in doBindObjectMethodIn
func (s *Server) doBindObjectRest(ctx context.Context, in doBindObjectInput) {
var (
handlerMap = make(map[string]*handlerItem)
handlerMap = make(map[string]*HandlerItem)
reflectValue = reflect.ValueOf(in.Object)
reflectType = reflectValue.Type()
initFunc func(*Request)
@ -290,7 +290,7 @@ func (s *Server) doBindObjectRest(ctx context.Context, in doBindObjectInput) {
}
key := s.mergeBuildInNameToPattern(methodName+":"+in.Pattern, structName, methodName, false)
handlerMap[key] = &handlerItem{
handlerMap[key] = &HandlerItem{
Name: fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, methodName),
Type: HandlerTypeObject,
Info: funcInfo,