server.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package rest
  2. import (
  3. "context"
  4. "errors"
  5. "net/http"
  6. "sync/atomic"
  7. "time"
  8. "git.ali33.ru/fcg-xvii/go-tools/json"
  9. "github.com/dgrijalva/jwt-go"
  10. )
  11. // IServer реализует интерфейс сервера для рест апи
  12. type IServer interface {
  13. // Addr возвращеат адрес, который сервер слушает
  14. Addr() string
  15. // Secret возвращает секретный ключ, при помощи которого генерируются токены авторизации пользователей
  16. Secret() []byte
  17. // HandleFunc устанавливает функцию обработчик, которая будет вызвана по обращению к URL, удовлетворяющему pattern
  18. HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
  19. // Listen запускает прослушивание сервера. Если не удалось успешно запустить прослушивание через
  20. // заданный временной интервал (timeout), будет возвращена ошибка
  21. Listen(timeout time.Duration, ctxParent context.Context) error
  22. // TokenGenerate - функция генерации токена авторизации
  23. TokenGenerate(m json.Map, expire int64) (string, error)
  24. // Close останавливает прослушивание
  25. Close() error
  26. // Context возвращает контекст сервера
  27. Context() context.Context
  28. }
  29. // NewServer создает сервер для реализации рест апи
  30. func NewServer(addr string, secret []byte) IServer {
  31. return &Server{
  32. secret: secret,
  33. server: &http.Server{
  34. Addr: addr,
  35. Handler: http.NewServeMux(),
  36. },
  37. }
  38. }
  39. func NewServerTLS(addr string, secret []byte, tlsKey, tlsCert string) IServer {
  40. serv := NewServer(addr, secret).(*Server)
  41. serv.tlsEnabled = true
  42. serv.tlsKey = tlsKey
  43. serv.tlsCert = tlsCert
  44. return serv
  45. }
  46. // Server реализует сервер для рест апи
  47. type Server struct {
  48. secret []byte
  49. server *http.Server
  50. opened atomic.Bool
  51. ctx context.Context
  52. cancel context.CancelFunc
  53. tlsEnabled bool
  54. tlsKey string
  55. tlsCert string
  56. }
  57. // Context возвращает контекст сервера
  58. func (s *Server) Context() context.Context {
  59. return s.ctx
  60. }
  61. // Close останавливает прослушивание
  62. func (s *Server) Close() error {
  63. if !s.opened.Load() {
  64. return errors.New("ErrNotOpened")
  65. }
  66. s.cancel()
  67. return nil
  68. }
  69. // Listen запускает прослушивание сервера. Если не удалось успешно запустить прослушивание через
  70. // заданный временной интервал (timeout), будет возвращена ошибка
  71. func (s *Server) Listen(timeout time.Duration, ctxParent context.Context) (err error) {
  72. if s.opened.Swap(true) {
  73. return errors.New("ErrAlreadyOpened")
  74. }
  75. ctx, _ := context.WithTimeout(ctxParent, timeout)
  76. go func() {
  77. var cancel context.CancelFunc
  78. s.ctx, cancel = context.WithCancel(ctxParent)
  79. if !s.tlsEnabled {
  80. err = s.server.ListenAndServe()
  81. } else {
  82. err = s.server.ListenAndServeTLS(s.tlsCert, s.tlsKey)
  83. }
  84. s.opened.Store(false)
  85. cancel()
  86. }()
  87. <-ctx.Done()
  88. if err == nil {
  89. go func() {
  90. <-s.ctx.Done()
  91. s.server.Close()
  92. }()
  93. }
  94. return
  95. }
  96. // TokenGenerate - функция генерации токена авторизации
  97. func (s *Server) TokenGenerate(m json.Map, expire int64) (string, error) {
  98. token := jwt.New(jwt.SigningMethodHS256)
  99. claims := token.Claims.(jwt.MapClaims)
  100. for key, val := range m {
  101. claims[key] = val
  102. }
  103. if expire > 0 {
  104. claims["exp"] = time.Now().Add(time.Minute * 30).Unix()
  105. }
  106. tokenString, err := token.SignedString(s.Secret())
  107. return tokenString, err
  108. }
  109. // Addr возвращеат адрес, который сервер слушает
  110. func (s *Server) Addr() string {
  111. return s.server.Addr
  112. }
  113. // Secret возвращает секретный ключ, при помощи которого генерируются токены авторизации пользователей
  114. func (s *Server) Secret() []byte {
  115. return s.secret
  116. }
  117. // HandleFunc устанавливает функцию обработчик, которая будет вызвана по обращению к URL, удовлетворяющему pattern
  118. func (s *Server) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
  119. s.server.Handler.(*http.ServeMux).HandleFunc(pattern, handler)
  120. }