1
0
mirror of https://github.com/go-kratos/kratos.git synced 2025-01-16 02:47:03 +02:00
kratos/transport/http/server.go

143 lines
3.3 KiB
Go
Raw Normal View History

2021-02-17 11:14:47 +02:00
package http
import (
"context"
2021-02-17 16:54:41 +02:00
"errors"
2021-02-17 11:14:47 +02:00
"fmt"
"net"
"net/http"
2021-05-28 09:08:25 +02:00
"strings"
2021-02-17 11:14:47 +02:00
"time"
"github.com/go-kratos/kratos/v2/internal/host"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/transport"
"github.com/gorilla/mux"
)
var _ transport.Server = (*Server)(nil)
2021-05-28 09:30:55 +02:00
var _ transport.Endpointer = (*Server)(nil)
2021-02-17 11:14:47 +02:00
// ServerOption is HTTP server option.
type ServerOption func(*Server)
// Network with server network.
func Network(network string) ServerOption {
return func(s *Server) {
s.network = network
}
}
// Address with server address.
func Address(addr string) ServerOption {
return func(s *Server) {
s.address = addr
}
}
// Timeout with server timeout.
func Timeout(timeout time.Duration) ServerOption {
return func(s *Server) {
s.timeout = timeout
}
}
// Logger with server logger.
func Logger(logger log.Logger) ServerOption {
return func(s *Server) {
s.log = log.NewHelper(logger)
2021-02-17 11:14:47 +02:00
}
}
// Server is a HTTP server wrapper.
type Server struct {
*http.Server
lis net.Listener
network string
address string
timeout time.Duration
router *mux.Router
log *log.Helper
2021-02-17 11:14:47 +02:00
}
// NewServer creates a HTTP server by options.
func NewServer(opts ...ServerOption) *Server {
srv := &Server{
network: "tcp",
address: ":0",
timeout: time.Second,
log: log.NewHelper(log.DefaultLogger),
2021-02-17 11:14:47 +02:00
}
for _, o := range opts {
o(srv)
}
srv.router = mux.NewRouter()
srv.Server = &http.Server{Handler: srv}
return srv
}
// Handle registers a new route with a matcher for the URL path.
func (s *Server) Handle(path string, h http.Handler) {
s.router.Handle(path, h)
}
// HandlePrefix registers a new route with a matcher for the URL path prefix.
func (s *Server) HandlePrefix(prefix string, h http.Handler) {
s.router.PathPrefix(prefix).Handler(h)
}
2021-02-17 11:14:47 +02:00
// HandleFunc registers a new route with a matcher for the URL path.
func (s *Server) HandleFunc(path string, h http.HandlerFunc) {
s.router.HandleFunc(path, h)
}
// ServeHTTP should write reply headers and data to the ResponseWriter and then return.
func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
ctx, cancel := context.WithTimeout(req.Context(), s.timeout)
defer cancel()
ctx = transport.NewContext(ctx, transport.Transport{Kind: transport.KindHTTP})
2021-02-17 11:14:47 +02:00
ctx = NewServerContext(ctx, ServerInfo{Request: req, Response: res})
s.router.ServeHTTP(res, req.WithContext(ctx))
2021-02-17 11:14:47 +02:00
}
// Endpoint return a real address to registry endpoint.
// examples:
// http://127.0.0.1:8000?isSecure=false
func (s *Server) Endpoint() (string, error) {
2021-05-28 09:30:55 +02:00
if s.lis == nil && strings.HasSuffix(s.address, ":0") {
2021-05-28 09:08:25 +02:00
lis, err := net.Listen(s.network, s.address)
if err != nil {
return "", err
}
s.lis = lis
}
2021-02-17 11:14:47 +02:00
addr, err := host.Extract(s.address, s.lis)
if err != nil {
return "", err
}
return fmt.Sprintf("http://%s", addr), nil
}
// Start start the HTTP server.
func (s *Server) Start() error {
2021-05-28 09:08:25 +02:00
if s.lis == nil {
lis, err := net.Listen(s.network, s.address)
if err != nil {
return err
}
s.lis = lis
2021-02-17 11:14:47 +02:00
}
2021-05-28 09:08:25 +02:00
s.log.Infof("[HTTP] server listening on: %s", s.lis.Addr().String())
if err := s.Serve(s.lis); !errors.Is(err, http.ErrServerClosed) {
2021-02-17 16:54:41 +02:00
return err
}
return nil
2021-02-17 11:14:47 +02:00
}
// Stop stop the HTTP server.
func (s *Server) Stop() error {
s.log.Info("[HTTP] server stopping")
return s.Shutdown(context.Background())
}