ctx.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package goproxy
  2. import (
  3. "crypto/tls"
  4. "net/http"
  5. "regexp"
  6. )
  7. // ProxyCtx is the Proxy context, contains useful information about every request. It is passed to
  8. // every user function. Also used as a logger.
  9. type ProxyCtx struct {
  10. // Will contain the client request from the proxy
  11. Req *http.Request
  12. // Will contain the remote server's response (if available. nil if the request wasn't send yet)
  13. Resp *http.Response
  14. RoundTripper RoundTripper
  15. // will contain the recent error that occurred while trying to send receive or parse traffic
  16. Error error
  17. // A handle for the user to keep data in the context, from the call of ReqHandler to the
  18. // call of RespHandler
  19. UserData interface{}
  20. // Will connect a request to a response
  21. Session int64
  22. certStore CertStorage
  23. Proxy *ProxyHttpServer
  24. }
  25. type RoundTripper interface {
  26. RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error)
  27. }
  28. type CertStorage interface {
  29. Fetch(hostname string, gen func() (*tls.Certificate, error)) (*tls.Certificate, error)
  30. }
  31. type RoundTripperFunc func(req *http.Request, ctx *ProxyCtx) (*http.Response, error)
  32. func (f RoundTripperFunc) RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) {
  33. return f(req, ctx)
  34. }
  35. func (ctx *ProxyCtx) RoundTrip(req *http.Request) (*http.Response, error) {
  36. if ctx.RoundTripper != nil {
  37. return ctx.RoundTripper.RoundTrip(req, ctx)
  38. }
  39. return ctx.Proxy.Tr.RoundTrip(req)
  40. }
  41. func (ctx *ProxyCtx) printf(msg string, argv ...interface{}) {
  42. ctx.Proxy.Logger.Printf("[%03d] "+msg+"\n", append([]interface{}{ctx.Session & 0xFF}, argv...)...)
  43. }
  44. // Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter
  45. // This message will be printed only if the Verbose field of the ProxyHttpServer is set to true
  46. //
  47. // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){
  48. // nr := atomic.AddInt32(&counter,1)
  49. // ctx.Printf("So far %d requests",nr)
  50. // return r, nil
  51. // })
  52. func (ctx *ProxyCtx) Logf(msg string, argv ...interface{}) {
  53. if ctx.Proxy.Verbose {
  54. ctx.printf("INFO: "+msg, argv...)
  55. }
  56. }
  57. // Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter
  58. // This message will always be printed.
  59. //
  60. // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){
  61. // f,err := os.OpenFile(cachedContent)
  62. // if err != nil {
  63. // ctx.Warnf("error open file %v: %v",cachedContent,err)
  64. // return r, nil
  65. // }
  66. // return r, nil
  67. // })
  68. func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{}) {
  69. ctx.printf("WARN: "+msg, argv...)
  70. }
  71. var charsetFinder = regexp.MustCompile("charset=([^ ;]*)")
  72. // Will try to infer the character set of the request from the headers.
  73. // Returns the empty string if we don't know which character set it used.
  74. // Currently it will look for charset=<charset> in the Content-Type header of the request.
  75. func (ctx *ProxyCtx) Charset() string {
  76. charsets := charsetFinder.FindStringSubmatch(ctx.Resp.Header.Get("Content-Type"))
  77. if charsets == nil {
  78. return ""
  79. }
  80. return charsets[1]
  81. }