package rest import ( "context" "errors" "net/http" "sync/atomic" "time" "git.ali33.ru/fcg-xvii/go-tools/json" "github.com/dgrijalva/jwt-go" ) type IServer interface { Addr() string Secret() []byte HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) Listen(timeout time.Duration) error TokenGenerate(m json.Map, expire int64) (string, error) Close() error Context() context.Context } func NewServer(addr string, secret []byte) IServer { return &Server{ secret: secret, server: &http.Server{ Addr: addr, Handler: http.NewServeMux(), }, } } type Server struct { secret []byte server *http.Server opened atomic.Bool ctx context.Context } func (s *Server) Context() context.Context { return s.ctx } func (s *Server) Close() error { if !s.opened.Load() { return errors.New("ErrNotOpened") } return s.server.Close() } func (s *Server) Listen(timeout time.Duration) (err error) { if s.opened.Swap(true) { return errors.New("ErrAlreadyOpened") } ctx, _ := context.WithTimeout(context.Background(), timeout) go func() { var cancel context.CancelFunc s.ctx, cancel = context.WithCancel(context.Background()) err = s.server.ListenAndServe() s.opened.Store(false) cancel() }() <-ctx.Done() return } func (s *Server) TokenGenerate(m json.Map, expire int64) (string, error) { token := jwt.New(jwt.SigningMethodHS256) claims := token.Claims.(jwt.MapClaims) for key, val := range m { claims[key] = val } if expire > 0 { claims["exp"] = time.Now().Add(time.Minute * 30).Unix() } tokenString, err := token.SignedString(s.Secret()) return tokenString, err } func (s *Server) Addr() string { return s.server.Addr } func (s *Server) Secret() []byte { return s.secret } func (s *Server) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) { s.server.Handler.(*http.ServeMux).HandleFunc(pattern, handler) }