Documentation
¶
Index ¶
- Variables
- func HTTPStatusCode(err error) int
- func NewContextWithRequest(ctx context.Context, r *http.Request) context.Context
- func NewGenericsHandler[REQUEST, RESPONSE any](f func(ctx context.Context, request *REQUEST) (response *RESPONSE, err error)) http.HandlerFunc
- func NewHandler(handling Handling) http.HandlerFunc
- func ReadRequest(ctx context.Context, dest interface{}, r *http.Request) error
- func ReadValidateRequest(ctx context.Context, dest interface{}, r *http.Request) error
- func RequestFromContext(ctx context.Context) *http.Request
- func WriteResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, ...) error
- type GenericsHandling
- type HTTPStatusError
- type HandleFunc
- type HandlerFactory
- type HandlerMiddleware
- type Handling
- type ReadRequestFunc
- type Server
- func (s *Server) ShutdownNotify() <-chan interface{}
- func (s *Server) Start(ctx context.Context) (listenAddr string, err error)
- func (s *Server) StartTLS(ctx context.Context, certFile, keyFile string) (listenAddr string, err error)
- func (s *Server) Stop(ctx context.Context)
- func (s *Server) Wait(ctx context.Context) error
- type WriteResponseFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultAccept = "*/*"
DefaultAccept 请求Header Accept的缺省值。
var DefaultHandlerFactory = HandlerFactory{ ReadRequestFunc: ReadRequest, Middleware: RecoveryMiddleware, WriteResponseFunc: WriteResponse, }
DefaultHandlerFactory 默认的Handler工厂。可修改,可覆盖。
var HandleRecovery = func(ctx context.Context, recovery interface{}) (overwriteRecovery interface{}) { return resterror.NewPanicError(recovery) }
HandleRecovery RecoveryMiddleware 的recovery处理函数。 默认处理,可覆盖。
var RequestErrorWrapper = func(ctx context.Context, err error) error { return resterror.ErrorWithStatus(err, resterror.StatusInvalidArgument) }
RequestErrorWrapper 请求处理错误包装。可以用来包装或覆盖请求错误。
var ValidateErrorWrapper = func(ctx context.Context, err error) error { return resterror.ErrorWithStatus(err, resterror.StatusInvalidArgument) }
ValidateErrorWrapper 请求校验错误包装。可以用来包装或覆盖请求错误。
Functions ¶
func HTTPStatusCode ¶
HTTPStatus err对应的HTTP状态文本和状态码。 如果err为nil,返回200; 如果err实现了HTTPStatusError接口,返回HTTPStatus()的结果; 否则返回500。
func NewContextWithRequest ¶
NewContextWithRequest 将*http.Request保存到上下文。
func NewGenericsHandler ¶
func NewGenericsHandler[REQUEST, RESPONSE any](f func(ctx context.Context, request *REQUEST) (response *RESPONSE, err error)) http.HandlerFunc
NewGenericsHandler 基于DefaultHandlerFactory和范型,创建一个http.Handler。
func NewHandler ¶
func NewHandler(handling Handling) http.HandlerFunc
NewHandler 基于DefaultHandlerFactory创建一个http.Handler。
Example ¶
type Request struct {
Greeting string `schema:"greeting" validate:"required"`
}
type Response struct {
Echo string `json:"echo"`
}
f := func(ctx context.Context, req *Request) (resp *Response, err error) {
return &Response{
Echo: req.Greeting,
}, nil
}
var handler http.HandlerFunc = NewGenericsHandler(f)
s := httptest.NewServer(handler)
defer s.Close()
client := s.Client()
resp, err := client.Get(s.URL + "/echo?greeting=hello")
if err != nil {
fmt.Println(err)
return
}
if resp.StatusCode != http.StatusOK {
fmt.Printf("status code: %d", resp.StatusCode)
return
}
data, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
Output: {"echo":"hello"}
Example (WithMiddleware) ¶
type Request struct {
Greeting string `schema:"greeting" validate:"required"`
}
type Response struct {
Echo string `json:"echo"`
}
middleware := ChainHandlerMiddlewares(func(next HandleFunc) HandleFunc {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := RequestFromContext(ctx)
fmt.Println(r.RequestURI)
response, err = next(ctx, request)
if err != nil {
return nil, err
}
return struct {
Data interface{} `json:"data"`
}{
Data: response,
}, nil
}
}, RecoveryMiddleware)
factory := DefaultHandlerFactory
factory.Middleware = middleware
f := func(ctx context.Context, req *Request) (resp *Response, err error) {
return &Response{
Echo: req.Greeting,
}, nil
}
var handler http.HandlerFunc = factory.NewHandler(GenericsHandling[Request, Response](f))
s := httptest.NewServer(handler)
defer s.Close()
client := s.Client()
resp, err := client.Get(s.URL + "/echo?greeting=hello")
if err != nil {
fmt.Println(err)
return
}
if resp.StatusCode != http.StatusOK {
fmt.Printf("status code: %d", resp.StatusCode)
return
}
data, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
Output: /echo?greeting=hello {"data":{"echo":"hello"}}
func ReadRequest ¶
ReadRequest 解析请求到对象。 支持GET的查询参数、POST/PUT/PATCH的Content-Type为application/json、application/x-www-form-urlencoded、application/x-protobuf的请求实体。 解析GET查询参数和application/x-www-form-urlencoded实体,需要dest对象字段带schema标签。
func ReadValidateRequest ¶
ReadValidateRequest 解析请求到对象。 会用github.com/go-playground/validator校验对象字段值。
func RequestFromContext ¶
RequestFromContext 从上下文中取得*http.Request对象。
func WriteResponse ¶
func WriteResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, response interface{}, err error) error
WriteResponse 将响应体写出。 response将被转为响应实体。 响应Content-Type根据请求的Accept推导。 如果err非nil,尝试转为HTTPStatusError接口,获取错误码。
Types ¶
type GenericsHandling ¶
type GenericsHandling[REQUEST, RESPONSE any] func(ctx context.Context, request *REQUEST) (response *RESPONSE, err error)
GenericsHandling 基于范型,将一个处理逻辑函数,转为Handling接口实现。
func (GenericsHandling[REQUEST, RESPONSE]) Handle ¶
func (handling GenericsHandling[REQUEST, RESPONSE]) Handle(ctx context.Context, req interface{}) (resp interface{}, err error)
Handle 处理请求,返回响应。实现Handling接口。
func (GenericsHandling[REQUEST, RESPONSE]) NewRequest ¶
func (handling GenericsHandling[REQUEST, RESPONSE]) NewRequest() interface{}
NewRequest 创建请求对象,返回请求对象的地址/指针。实现Handling接口。
type HTTPStatusError ¶
HTTPStatusError 提供Http状态码的错误接口。
type HandleFunc ¶
HandleFunc Handling的Handle方法的类型。
func RecoveryMiddleware ¶
func RecoveryMiddleware(next HandleFunc) HandleFunc
RecoveryMiddleware 处理panic的中间件。recover()返回值将被转为error。
type HandlerFactory ¶
type HandlerFactory struct {
// ReadRequestFunc 读请求函数。默认是:ReadRequest。
ReadRequestFunc ReadRequestFunc
// Middleware 中间件。多个中间件可以用ChainHandlerMiddlewares串联起来。默认是:RecoveryMiddleware。
Middleware HandlerMiddleware
// WriteResponseFunc 写响应的函数的签名。默认是:WriteResponse。
WriteResponseFunc WriteResponseFunc
}
HandlerFactory Handler工厂。
func (HandlerFactory) NewHandler ¶
func (factory HandlerFactory) NewHandler(handling Handling) http.HandlerFunc
NewHandler 创建一个http.Handler。
type HandlerMiddleware ¶
type HandlerMiddleware func(next HandleFunc) HandleFunc
HandlerMiddleware Handler中间件。
func ChainHandlerMiddlewares ¶
func ChainHandlerMiddlewares(middlewares ...HandlerMiddleware) HandlerMiddleware
HandlerMiddlewareChain 中间件链。
type Handling ¶
type Handling interface {
// NewRequest 创建请求对象,返回请求对象的地址/指针。
NewRequest() interface{}
// Handle 处理请求,返回响应。
Handle(ctx context.Context, request interface{}) (response interface{}, err error)
}
Handling 处理逻辑的接口。GenericsHandling实现了该接口。
type ReadRequestFunc ¶
ReadRequestFunc 解析请求的函数的签名。
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server http.Server的包装。 支持收到SIGTERM、SIGINT信号时结束监听。 支持等待全部处理过程结束。
Example ¶
type Request struct {
Greeting string `schema:"greeting" validate:"required"`
}
type Response struct {
Echo string `json:"echo"`
}
ctx := context.Background()
s := NewServer(ctx, &http.Server{
Addr: "127.0.0.1:28080",
Handler: http.HandlerFunc(NewHandler(GenericsHandling[Request, Response](func(ctx context.Context, req *Request) (*Response, error) {
return &Response{
Echo: req.Greeting,
}, nil
}))),
})
addr, err := s.Start(ctx) // 启动监听,开始服务。直至收到SIGTERM、SIGINT信号,或Stop被调用。
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Listen running at:", addr)
resp, err := http.Get("http://" + addr + "/echo?greeting=Hello")
if err != nil {
fmt.Println(err)
return
}
if resp.StatusCode != http.StatusOK {
fmt.Printf("status code: %d", resp.StatusCode)
return
}
data, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
s.Stop(ctx) // 结束监听。实际环境应该是内部接收退出信号
<-s.ShutdownNotify()
fmt.Println("exiting")
err = s.Wait(ctx) // 等待处理完
if err != nil {
fmt.Println(err)
return
}
fmt.Println("exited")
Output: Listen running at: 127.0.0.1:28080 {"echo":"Hello"} exiting exited
func (*Server) ShutdownNotify ¶
func (s *Server) ShutdownNotify() <-chan interface{}
ShutdownNotify 服务关闭通知。
type WriteResponseFunc ¶
type WriteResponseFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, response interface{}, err error) error
WriteResponseFunc 输出响应的函数的签名。
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package mock_httpserver is a generated GoMock package.
|
Package mock_httpserver is a generated GoMock package. |
|
cache_example
command
|