client.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package api
  2. import (
  3. "context"
  4. "github.com/go-resty/resty/v2"
  5. "log"
  6. "time"
  7. )
  8. const (
  9. EnteAPIEndpoint = "https://api.ente.io"
  10. TokenHeader = "X-Auth-Token"
  11. TokenQuery = "token"
  12. ClientPkgHeader = "X-Client-Package"
  13. )
  14. var (
  15. RedactedHeaders = []string{TokenHeader, " X-Request-Id"}
  16. )
  17. var tokenMap map[string]string = make(map[string]string)
  18. type Client struct {
  19. restClient *resty.Client
  20. // use separate client for downloading files
  21. downloadClient *resty.Client
  22. }
  23. type Params struct {
  24. Debug bool
  25. Trace bool
  26. Host string
  27. }
  28. func readValueFromContext(ctx context.Context, key string) interface{} {
  29. value := ctx.Value(key)
  30. return value
  31. }
  32. func NewClient(p Params) *Client {
  33. enteAPI := resty.New()
  34. if p.Trace {
  35. enteAPI.EnableTrace()
  36. }
  37. enteAPI.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
  38. app := readValueFromContext(req.Context(), "app")
  39. if app == nil {
  40. panic("app not set in context")
  41. }
  42. req.Header.Set(ClientPkgHeader, StringToApp(app.(string)).ClientPkg())
  43. attachToken(req)
  44. return nil
  45. })
  46. if p.Debug {
  47. enteAPI.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
  48. logRequest(req)
  49. return nil
  50. })
  51. enteAPI.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
  52. logResponse(resp)
  53. return nil
  54. })
  55. }
  56. if p.Host != "" {
  57. enteAPI.SetBaseURL(p.Host)
  58. } else {
  59. enteAPI.SetBaseURL(EnteAPIEndpoint)
  60. }
  61. return &Client{
  62. restClient: enteAPI,
  63. downloadClient: resty.New().
  64. SetRetryCount(3).
  65. SetRetryWaitTime(5 * time.Second).
  66. SetRetryMaxWaitTime(10 * time.Second).
  67. AddRetryCondition(func(r *resty.Response, err error) bool {
  68. shouldRetry := r.StatusCode() == 429 || r.StatusCode() > 500
  69. if shouldRetry {
  70. log.Printf("retrying download due to %d code", r.StatusCode())
  71. }
  72. return shouldRetry
  73. }),
  74. }
  75. }
  76. func attachToken(req *resty.Request) {
  77. accountKey := readValueFromContext(req.Context(), "account_key")
  78. if accountKey != nil && accountKey != "" {
  79. if token, ok := tokenMap[accountKey.(string)]; ok {
  80. req.SetHeader(TokenHeader, token)
  81. }
  82. }
  83. }
  84. func (c *Client) AddToken(id string, token string) {
  85. tokenMap[id] = token
  86. }