sysapihandler.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package api
  2. import (
  3. "context"
  4. "errors"
  5. "net/http"
  6. "strconv"
  7. "strings"
  8. "github.com/go-chi/render"
  9. )
  10. //APIKeyHeader in this header thr right api key should be inserted
  11. const APIKeyHeader = "X-mcs-apikey"
  12. //SystemHeader in this header thr right system should be inserted
  13. const SystemHeader = "X-mcs-system"
  14. //SysAPIKey defining a handler for checking system id and api key
  15. type SysAPIKey struct {
  16. SystemID string
  17. Apikey string
  18. }
  19. //NewSysAPIHandler creates a new SysApikeyHandler
  20. func NewSysAPIHandler(systemID string, apikey string) *SysAPIKey {
  21. c := &SysAPIKey{
  22. SystemID: systemID,
  23. Apikey: apikey,
  24. }
  25. return c
  26. }
  27. //Handler the handler checks systemid and apikey headers
  28. func (s *SysAPIKey) Handler(next http.Handler) http.Handler {
  29. return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
  30. path := strings.TrimSuffix(request.URL.Path, "/")
  31. if !strings.HasPrefix(path, "/health") && !strings.HasPrefix(path, "/files") {
  32. if s.SystemID != request.Header.Get(SystemHeader) {
  33. render.Render(response, request, ErrInvalidRequest(errors.New("either system id or apikey not correct")))
  34. return
  35. }
  36. if s.Apikey != strings.ToLower(request.Header.Get(APIKeyHeader)) {
  37. render.Render(response, request, ErrInvalidRequest(errors.New("either system id or apikey not correct")))
  38. return
  39. }
  40. }
  41. next.ServeHTTP(response, request)
  42. })
  43. }
  44. //AddHeader adding gefault header for system and apikey
  45. func AddHeader(response http.ResponseWriter, apikey string, system string) {
  46. response.Header().Add(APIKeyHeader, apikey)
  47. response.Header().Add(SystemHeader, system)
  48. }
  49. var (
  50. contextKeyOffset = contextKey("offset")
  51. contextKeyLimit = contextKey("limit")
  52. )
  53. //Paginate is a middleware logic for populating the context with offset and limit values
  54. func Paginate(next http.Handler) http.Handler {
  55. return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
  56. ctx := request.Context()
  57. offsetStr := request.URL.Query().Get("offset")
  58. limitStr := request.URL.Query().Get("limit")
  59. if offsetStr != "" {
  60. offset, err := strconv.Atoi(offsetStr)
  61. if err != nil {
  62. render.Render(response, request, ErrInvalidRequest(err))
  63. return
  64. }
  65. ctx = context.WithValue(ctx, contextKeyOffset, offset)
  66. } else {
  67. ctx = context.WithValue(ctx, contextKeyOffset, 0)
  68. }
  69. if limitStr != "" {
  70. limit, err := strconv.Atoi(limitStr)
  71. if err != nil {
  72. render.Render(response, request, ErrInvalidRequest(err))
  73. return
  74. }
  75. ctx = context.WithValue(ctx, contextKeyLimit, limit)
  76. } else {
  77. ctx = context.WithValue(ctx, contextKeyLimit, 0)
  78. }
  79. next.ServeHTTP(response, request.WithContext(ctx))
  80. })
  81. }
  82. type contextKey string
  83. func (c contextKey) String() string {
  84. return "api" + string(c)
  85. }