server.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package server
  2. import (
  3. "context"
  4. "fmt"
  5. golog "log"
  6. "net"
  7. "net/http"
  8. log "github.com/sirupsen/logrus"
  9. "golang.org/x/net/netutil"
  10. "github.com/imgproxy/imgproxy/v3/config"
  11. "github.com/imgproxy/imgproxy/v3/reuseport"
  12. )
  13. const (
  14. // maxHeaderBytes represents max bytes in request header
  15. maxHeaderBytes = 1 << 20
  16. )
  17. // Server represents the HTTP server wrapper struct
  18. type Server struct {
  19. router *Router
  20. server *http.Server
  21. Addr net.Addr
  22. }
  23. // Start starts the http server. cancel is called in case server failed to start, but it happened
  24. // asynchronously. It should cancel the upstream context.
  25. func Start(cancel context.CancelFunc, router *Router) (*Server, error) {
  26. l, err := reuseport.Listen(router.config.Network, router.config.Bind, router.config.SocketReusePort)
  27. if err != nil {
  28. cancel()
  29. return nil, fmt.Errorf("can't start server: %s", err)
  30. }
  31. if router.config.MaxClients > 0 {
  32. l = netutil.LimitListener(l, router.config.MaxClients)
  33. }
  34. errLogger := golog.New(
  35. log.WithField("source", "http_server").WriterLevel(log.ErrorLevel),
  36. "", 0,
  37. )
  38. addr := l.Addr()
  39. srv := &http.Server{
  40. Handler: router,
  41. ReadTimeout: router.config.ReadRequestTimeout,
  42. MaxHeaderBytes: maxHeaderBytes,
  43. ErrorLog: errLogger,
  44. }
  45. if config.KeepAliveTimeout > 0 {
  46. srv.IdleTimeout = router.config.KeepAliveTimeout
  47. } else {
  48. srv.SetKeepAlivesEnabled(false)
  49. }
  50. go func() {
  51. log.Infof("Starting server at %s", router.config.Bind)
  52. if err := srv.Serve(l); err != nil && err != http.ErrServerClosed {
  53. log.Error(err)
  54. }
  55. cancel()
  56. }()
  57. return &Server{
  58. router: router,
  59. server: srv,
  60. Addr: addr,
  61. }, nil
  62. }
  63. // Shutdown gracefully shuts down the server
  64. func (s *Server) Shutdown(ctx context.Context) {
  65. log.Info("Shutting down the server...")
  66. ctx, close := context.WithTimeout(ctx, s.router.config.GracefulTimeout)
  67. defer close()
  68. s.server.Shutdown(ctx)
  69. }