cookies.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package cookies
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/http/cookiejar"
  6. "net/url"
  7. "sync"
  8. "golang.org/x/net/publicsuffix"
  9. "github.com/imgproxy/imgproxy/v3/config"
  10. "github.com/imgproxy/imgproxy/v3/ierrors"
  11. )
  12. type cookieError string
  13. func (e cookieError) Error() string { return string(e) }
  14. type anyCookieJarEntry struct {
  15. Name string
  16. Value string
  17. Quoted bool
  18. }
  19. // anyCookieJar is a cookie jar that stores all cookies in memory
  20. // and doesn't care about domains and paths
  21. type anyCookieJar struct {
  22. entries []anyCookieJarEntry
  23. mu sync.RWMutex
  24. }
  25. func (j *anyCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
  26. j.mu.Lock()
  27. defer j.mu.Unlock()
  28. for _, c := range cookies {
  29. entry := anyCookieJarEntry{
  30. Name: c.Name,
  31. Value: c.Value,
  32. Quoted: c.Quoted,
  33. }
  34. j.entries = append(j.entries, entry)
  35. }
  36. }
  37. func (j *anyCookieJar) Cookies(u *url.URL) []*http.Cookie {
  38. j.mu.RLock()
  39. defer j.mu.RUnlock()
  40. cookies := make([]*http.Cookie, 0, len(j.entries))
  41. for _, e := range j.entries {
  42. c := http.Cookie{
  43. Name: e.Name,
  44. Value: e.Value,
  45. Quoted: e.Quoted,
  46. }
  47. cookies = append(cookies, &c)
  48. }
  49. return cookies
  50. }
  51. func JarFromRequest(r *http.Request) (jar http.CookieJar, err error) {
  52. if config.CookiePassthroughAll {
  53. jar = &anyCookieJar{}
  54. } else {
  55. jar, err = cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
  56. if err != nil {
  57. return nil, err
  58. }
  59. }
  60. if r == nil {
  61. return jar, nil
  62. }
  63. var cookieBase *url.URL
  64. if !config.CookiePassthroughAll {
  65. if len(config.CookieBaseURL) > 0 {
  66. if cookieBase, err = url.Parse(config.CookieBaseURL); err != nil {
  67. return nil, ierrors.Wrap(cookieError(fmt.Sprintf("can't parse cookie base URL: %s", err)), 0)
  68. }
  69. }
  70. if cookieBase == nil {
  71. scheme := r.Header.Get("X-Forwarded-Proto")
  72. if len(scheme) == 0 {
  73. scheme = "http"
  74. }
  75. host := r.Header.Get("X-Forwarded-Host")
  76. if len(host) == 0 {
  77. host = r.Header.Get("Host")
  78. }
  79. if len(host) == 0 {
  80. host = r.Host
  81. }
  82. if len(host) == 0 {
  83. return jar, nil
  84. }
  85. port := r.Header.Get("X-Forwarded-Port")
  86. if len(port) > 0 {
  87. host = host + ":" + port
  88. }
  89. cookieBase = &url.URL{
  90. Scheme: scheme,
  91. Host: host,
  92. }
  93. }
  94. }
  95. jar.SetCookies(cookieBase, r.Cookies())
  96. return jar, nil
  97. }