server.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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) 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. // Server реализует сервер для рест апи
  40. type Server struct {
  41. secret []byte
  42. server *http.Server
  43. opened atomic.Bool
  44. ctx context.Context
  45. }
  46. // Context возвращает контекст сервера
  47. func (s *Server) Context() context.Context {
  48. return s.ctx
  49. }
  50. // Close останавливает прослушивание
  51. func (s *Server) Close() error {
  52. if !s.opened.Load() {
  53. return errors.New("ErrNotOpened")
  54. }
  55. return s.server.Close()
  56. }
  57. // Listen запускает прослушивание сервера. Если не удалось успешно запустить прослушивание через
  58. // заданный временной интервал (timeout), будет возвращена ошибка
  59. func (s *Server) Listen(timeout time.Duration) (err error) {
  60. if s.opened.Swap(true) {
  61. return errors.New("ErrAlreadyOpened")
  62. }
  63. ctx, _ := context.WithTimeout(context.Background(), timeout)
  64. go func() {
  65. var cancel context.CancelFunc
  66. s.ctx, cancel = context.WithCancel(context.Background())
  67. err = s.server.ListenAndServe()
  68. s.opened.Store(false)
  69. cancel()
  70. }()
  71. <-ctx.Done()
  72. return
  73. }
  74. // TokenGenerate - функция генерации токена авторизации
  75. func (s *Server) TokenGenerate(m json.Map, expire int64) (string, error) {
  76. token := jwt.New(jwt.SigningMethodHS256)
  77. claims := token.Claims.(jwt.MapClaims)
  78. for key, val := range m {
  79. claims[key] = val
  80. }
  81. if expire > 0 {
  82. claims["exp"] = time.Now().Add(time.Minute * 30).Unix()
  83. }
  84. tokenString, err := token.SignedString(s.Secret())
  85. return tokenString, err
  86. }
  87. // Addr возвращеат адрес, который сервер слушает
  88. func (s *Server) Addr() string {
  89. return s.server.Addr
  90. }
  91. // Secret возвращает секретный ключ, при помощи которого генерируются токены авторизации пользователей
  92. func (s *Server) Secret() []byte {
  93. return s.secret
  94. }
  95. // HandleFunc устанавливает функцию обработчик, которая будет вызвана по обращению к URL, удовлетворяющему pattern
  96. func (s *Server) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
  97. s.server.Handler.(*http.ServeMux).HandleFunc(pattern, handler)
  98. }