http_proxy_base_cookietracker.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package http_proxy
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strings"
  6. "sync"
  7. "github.com/elazarl/goproxy"
  8. "github.com/jpillora/go-tld"
  9. )
  10. type CookieTracker struct {
  11. sync.RWMutex
  12. set map[string]bool
  13. }
  14. func NewCookieTracker() *CookieTracker {
  15. return &CookieTracker{
  16. set: make(map[string]bool),
  17. }
  18. }
  19. func (t *CookieTracker) domainOf(req *http.Request) string {
  20. if parsed, err := tld.Parse(req.Host); err != nil {
  21. return req.Host
  22. } else {
  23. return fmt.Sprintf("%s.%s", parsed.Domain, parsed.TLD)
  24. }
  25. }
  26. func (t *CookieTracker) keyOf(req *http.Request) string {
  27. client := strings.Split(req.RemoteAddr, ":")[0]
  28. domain := t.domainOf(req)
  29. return fmt.Sprintf("%s-%s", client, domain)
  30. }
  31. func (t *CookieTracker) IsClean(req *http.Request) bool {
  32. // we only clean GET requests
  33. if req.Method != "GET" {
  34. return true
  35. }
  36. // does the request have any cookie?
  37. cookie := req.Header.Get("Cookie")
  38. if cookie == "" {
  39. return true
  40. }
  41. t.RLock()
  42. defer t.RUnlock()
  43. // was it already processed?
  44. if _, found := t.set[t.keyOf(req)]; found {
  45. return true
  46. }
  47. // unknown session cookie
  48. return false
  49. }
  50. func (t *CookieTracker) Track(req *http.Request) {
  51. t.Lock()
  52. defer t.Unlock()
  53. t.set[t.keyOf(req)] = true
  54. }
  55. func (t *CookieTracker) Expire(req *http.Request) *http.Response {
  56. domain := t.domainOf(req)
  57. redir := goproxy.NewResponse(req, "text/plain", 302, "")
  58. for _, c := range req.Cookies() {
  59. redir.Header.Add("Set-Cookie", fmt.Sprintf("%s=EXPIRED; path=/; domain=%s; Expires=Mon, 01-Jan-1990 00:00:00 GMT", c.Name, domain))
  60. redir.Header.Add("Set-Cookie", fmt.Sprintf("%s=EXPIRED; path=/; domain=%s; Expires=Mon, 01-Jan-1990 00:00:00 GMT", c.Name, c.Domain))
  61. }
  62. redir.Header.Add("Location", fmt.Sprintf("http://%s/", req.Host))
  63. redir.Header.Add("Connection", "close")
  64. return redir
  65. }