ctx.go 2.9 KB

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