trpc.group/trpc-go/trpc-go@v1.0.3/admin/router.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package admin
    15  
    16  import (
    17  	"encoding/json"
    18  	"fmt"
    19  	"net/http"
    20  	"runtime"
    21  	"sync"
    22  
    23  	"trpc.group/trpc-go/trpc-go/internal/report"
    24  	"trpc.group/trpc-go/trpc-go/log"
    25  )
    26  
    27  // PanicBufLen is the length of the buffer used for stack trace logging
    28  // when goroutine panics, default is 1024.
    29  const panicBufLen = 1024
    30  
    31  // newRouter creates a new Router.
    32  func newRouter() *router {
    33  	return &router{
    34  		ServeMux: http.NewServeMux(),
    35  	}
    36  }
    37  
    38  // newRouterHandler creates a new restful route info handler.
    39  func newRouterHandler(pattern string, handler http.HandlerFunc) *routerHandler {
    40  	return &routerHandler{
    41  		pattern: pattern,
    42  		handler: handler,
    43  	}
    44  }
    45  
    46  type router struct {
    47  	*http.ServeMux
    48  
    49  	sync.RWMutex
    50  	handlers map[string]*routerHandler
    51  }
    52  
    53  // add adds a routing pattern and handler function.
    54  func (r *router) add(pattern string, handler http.HandlerFunc) *routerHandler {
    55  	r.Lock()
    56  	defer r.Unlock()
    57  
    58  	r.ServeMux.HandleFunc(pattern, handler)
    59  	if r.handlers == nil {
    60  		r.handlers = make(map[string]*routerHandler)
    61  	}
    62  
    63  	h := newRouterHandler(pattern, handler)
    64  	r.handlers[pattern] = h
    65  	return h
    66  }
    67  
    68  // ServeHTTP handles incoming HTTP requests.
    69  func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    70  	defer func() {
    71  		if err := recover(); err != nil {
    72  			buf := make([]byte, panicBufLen)
    73  			buf = buf[:runtime.Stack(buf, false)]
    74  			log.Errorf("[PANIC]%v\n%s\n", err, buf)
    75  			report.AdminPanicNum.Incr()
    76  			ret := newDefaultRes()
    77  			ret[retErrCode] = http.StatusInternalServerError
    78  			ret[retMessage] = fmt.Sprintf("PANIC : %v", err)
    79  			_ = json.NewEncoder(w).Encode(ret)
    80  		}
    81  	}()
    82  	r.ServeMux.ServeHTTP(w, req)
    83  }
    84  
    85  // list returns a list of configured routes.
    86  func (r *router) list() []*routerHandler {
    87  	l := make([]*routerHandler, 0, len(r.handlers))
    88  	for _, handler := range r.handlers {
    89  		l = append(l, handler)
    90  	}
    91  	return l
    92  }
    93  
    94  // routerHandler routing information handler.
    95  type routerHandler struct {
    96  	handler http.HandlerFunc
    97  	pattern string
    98  }