mirror of
https://gitee.com/johng/gf
synced 2026-07-04 13:02:36 +08:00
improve package ghttp
This commit is contained in:
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
Reference in New Issue
Block a user