goproxy

package module
v0.0.0-...-e630cc2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 6, 2013 License: BSD-3-Clause Imports: 14 Imported by: 0

README

Beta Software

I've received a positive feedback from a few people who use goproxy in production settings. I believe it is good enough for usage.

I'll try to keep reasonable backwards compatability. In case of a major API change, I'll change the import path.

Introduction

Package goproxy provides a customizable HTTP proxy library for Go (golang),

It supports regular HTTP proxy, HTTPS through CONNECT, and "hijacking" HTTPS connection using "Man in the Middle" style attack.

The intent of the proxy, is to be usable with reasonable amount of traffic yet, customizable and programable.

The proxy itself is simply a net/http handler.

Why not Fiddler2?

Fiddler is an excellent software with similar intent. However, Fiddler is not as customable as goproxy intend to be. The main difference is, Fiddler is not intended to be used as a real proxy.

A possible use case that suits goproxy but not Fiddler, is, gathering statisitics on page load times for a certain website over a week. With goproxy you could ask all your users to set their proxy to a dedicated machine running a goproxy server. Fiddler is a GUI app not designed to be ran like a server for multiple users.

A taste of goproxy

To get a taste of goproxy, a basic HTTP/HTTPS transparent proxy

import (
    "github.com/elazarl/goproxy"
    "log"
    "net/http"
)

func main() {
    proxy := goproxy.NewProxyHttpServer()
    proxy.Verbose = true
    log.Fatal(http.ListenAndServe(":8080", proxy))
}

This line will add X-GoProxy: yxorPoG-X header to all requests sent through the proxy

proxy.OnRequest().DoFunc(
    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
        r.Header.Set("X-GoProxy","yxorPoG-X")
        return r,nil
    }
)

DoFunc will process all incoming requests to the proxy. It will add a header to the request and return it. The proxy will send the modified request.

Note that we returned nil value as the response. Have we returned a response, goproxy would have discarded the request and sent the new response to the client.

In order to refuse connections to reddit at work time

proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
        if h,_,_ := time.Now().Clock(); h >= 8 && h <= 17 {
            return r,goproxy.NewResponse(r,
                    goproxy.ContentTypeText,http.StatusForbidden,
                    "Don't waste your time!")
        }
        return r,nil
})

DstHostIs returns a ReqCondition, that is a function receiving a Request and returning a boolean we will only process requests that matches the condition. DstHostIs("www.reddit.com") will return a ReqCondition accepting only requests directed to "www.reddit.com".

DoFunc will recieve a function that will preprocess the request. We can change the request, or return a response. If the time is between 8:00am and 17:00pm, we will neglect the request, and return a precanned text response saying "do not waste your time".

See additional examples in the examples directory.

License

I put the software temporarily under the Go-compatible BSD license, if this prevents someone from using the software, do let mee know and I'll consider changing it.

At any rate, user feedback is very important for me, so I'll be delighted to know if you're using this package.

Documentation

Overview

Package goproxy provides a customizable HTTP proxy, supporting hijacking HTTPS connection.

The intent of the proxy, is to be usable with reasonable amount of traffic yet, customizable and programable.

The proxy itself is simply an `net/http` handler.

Typical usage is

proxy := goproxy.NewProxyHttpServer()
proxy.OnRequest(..conditions..).Do(..requesthandler..)
proxy.OnRequest(..conditions..).DoFunc(..requesthandlerFunction..)
proxy.OnReponse(..conditions..).Do(..responesHandler..)
proxy.OnReponse(..conditions..).DoFunc(..responesHandlerFunction..)
http.ListenAndServe(":8080", proxy)

Adding a header to each request

proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx)*http.Request{
	r.Header.Set("X-GoProxy","1")
	return r
})

Note that the function is called before the proxy sends the request to the server

For printing the content type of all incoming responses

proxy.OnReponse().DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{
	println(ctx.Req.Host,"->",r.Header.Get("Content-Type"))
	return r
})

note that we used the ProxyCtx context variable here. It contains the request and the response (Req and Resp, Resp is nil if unavailable) of this specific client interaction with the proxy.

To print the content type of all responses from a certain url, we'll add a ReqCondition to the OnResponse function:

proxy.OnReponse(goproxy.UrlIs("golang.org/pkg")).DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{
	println(ctx.Req.Host,"->",r.Header.Get("Content-Type"))
	return r
})

We can write the condition ourselves, conditions can be set on request and on response

var random = ReqConditionFunc(func(r *http.Request) bool {
	return rand.Intn(1) == 0
})
var hasGoProxyHeader = RespConditionFunc(func(resp *http.Response,req *http.Request)bool {
	return resp.Header.Get("X-GoProxy") != ""
})

Caution! If you give a RespCondition to the OnRequest function, you'll get a run time panic! It doesn't make sense to read the response, if you still haven't got it!

Finally, we have convenience function to throw a quick response

proxy.OnResponse(hasGoProxyHeader).DoFunc(func(r*http.Response,ctx *goproxy.ProxyCtx)*http.Response {
	r.Body.Close()
	return goproxy.ForbiddenTextResponse(ctx.Req,"Can't see response with X-GoProxy header!")
})

we close the body of the original repsonse, and return a new 403 response with a short message.

Example use cases:

https://github.com/elazarl/goproxy/examples/avgSize

To measure the average size of an Html served in your site. One can ask all the QA team to access the website by a proxy, and the proxy will measure the average size of all text/html responses from your host.

[not yet implemented]

All requests to your web servers should be directed through the proxy, when the proxy will detect html pieces sent as a response to AJAX request, it'll send a warning email.

[not yet implemented]

Generate a real traffic to your website by real users using through proxy. Record the traffic, and try it again for more real load testing.

[not yet implemented]

Will allow browsing to reddit.com between 8:00am and 17:00pm

[not yet implemented]

Will warn if multiple versions of jquery are used in the same domain.

Index

Constants

View Source
const (
	ConnectAccept = iota
	ConnectReject
	ConnectMitm
)
View Source
const (
	ContentTypeText = "text/plain"
	ContentTypeHtml = "text/html"
)

Variables

View Source
var (
	OkConnect     = &ConnectAction{Action: ConnectAccept}
	MitmConnect   = &ConnectAction{Action: ConnectMitm}
	RejectConnect = &ConnectAction{Action: ConnectReject}
)
View Source
var SERVER_CERT = []byte(`-----BEGIN CERTIFICATE-----
MIICATCCAWoCCQD/6eUeFn3yRDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMB4XDTExMDYwMzEzMjEwMVoXDTEyMDYwMjEzMjEwMVowRTELMAkG
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0OwS
N2h83OXkzdv8azyvAwFsAWJZPyV8oLvL05OIUb+RgvzeA1FL3YXsRR1dIBLqD7H8
OmS1ZctpQ61N8dOKISTohGdkK0l3X1ZKNDlwCgHwYl0+GfX63kM7NoNeevA3/paT
Tej4d+MEZ/xKugCwNeKb1M9ULAB9fMGBrLP4D3MCAwEAATANBgkqhkiG9w0BAQUF
AAOBgQAITr5Ly40GBFfaYquy1IhhqbIzaTg8JaPnd7yBvxoez4U7D4SB8Gu90QdW
0t2fPdiNmLaUzHckPnSJURiUjXW1v7eEDCAN6Gxc2TVt/wc4xshgCiOL7XBqxmNA
c1kT5IqLS7CMqOnSBNCaTtQxba3E/xi8BcODJ8aeFw6AGU7O+A==
-----END CERTIFICATE-----`)

server certificate used when interception HTTPS traffic

View Source
var SERVER_KEY = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDQ7BI3aHzc5eTN2/xrPK8DAWwBYlk/JXygu8vTk4hRv5GC/N4D
UUvdhexFHV0gEuoPsfw6ZLVly2lDrU3x04ohJOiEZ2QrSXdfVko0OXAKAfBiXT4Z
9freQzs2g1568Df+lpNN6Ph34wRn/Eq6ALA14pvUz1QsAH18wYGss/gPcwIDAQAB
AoGAF0mJCkYKTPEPHOcdbrKX62TYLhtRSVmbV6s3IAE826fXx1r6QDJqm2mXGWkZ
fT6+ejtjmvqowYz30cRagM8MgUuTRkDUhKMbAzSEO8uCEEoTLDOZpUUCSOg78WUH
jV04INJi6jpduPj5vjm81gcTvE0+jB8KLCQeu8PoVZKC5WkCQQD4x1rsjP4tfyCl
K/SXD2ou3Nlwf6wHH5CXXHbmzX3WnP0eFMJ5s3dKFlX4Kgl9eMTQC6zYsaqc22uq
lqOuEGetAkEA1vyL6okLsKQFp+vPAqZMw6P6gw4XEeG4MD0H+ruWxzLaIfqLq4w8
ZNQqWu5EyfHUfpNVFIR3ST+8ZkpW5be3nwJAIIwESzpO7qjZHoLXpwOvQp5GHD+3
w97PTd4c+CkeM3uqacsRflaKXrj5WlQ1laK9LPK6FEd6KLdUKKc4lscyqQJAemJy
VCWIHhqBjcJTqjJ5aLYkmg6fW3Kfo/ZaYIYBo4xzWPyEHjhK+Ss+oV0ak8uzKAs/
V9rA/VXnLmQLa+JWCQJAPxvmm5VLT0lFh6gYswvEJtUnJ++x1axbGlNxx+cg+vbT
QSD5/EcAsiDP5HgX2BQ8VubV+cruuuOew56wcLjS/Q==
-----END RSA PRIVATE KEY-----`)

server private key used when interception HTTPS traffic

Functions

func NewResponse

func NewResponse(r *http.Request, contentType string, status int, body string) *http.Response

Will generate a valid http response to the given request the response will have the given contentType, and http status. Typical usage, refuse to process requests to local addresses:

proxy.OnRequest(IsLocalHost()).DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request,*http.Response) {
	return nil,NewResponse(r,goproxy.ContentTypeHtml,http.StatusUnauthorized,
		`<!doctype html><html><head><title>Can't use proxy for local addresses</title></head><body/></html>`)
})

func TextResponse

func TextResponse(r *http.Request, text string) *http.Response

Alias for NewResponse(r,ContentTypeText,http.StatusAccepted,text)

Types

type ConnectAction

type ConnectAction struct {
	Action    ConnectActionLiteral
	TlsConfig *tls.Config
}

type ConnectActionLiteral

type ConnectActionLiteral int

type FuncHttpsHandler

type FuncHttpsHandler func(host string, ctx *ProxyCtx) (*ConnectAction, string)

A wrapper that would convert a function to a HttpsHandler interface type

var AlwaysMitm FuncHttpsHandler = func(host string, ctx *ProxyCtx) (*ConnectAction, string) {
	return MitmConnect, host
}

AlwaysMitm is a HttpsHandler that always eavesdrop https connections, for example to eavesdrop all https connections to www.google.com, we can use

proxy.OnRequest(goproxy.ReqHostIs("www.google.com")).HandleConnect(goproxy.AlwaysMitm)
var AlwaysReject FuncHttpsHandler = func(host string, ctx *ProxyCtx) (*ConnectAction, string) {
	return RejectConnect, host
}

AlwaysReject is a HttpsHandler that drops any CONNECT request, for example, this code will disallow connections to hosts on any other port than 443

proxy.OnRequest(goproxy.Not(goproxy.ReqHostMatches(regexp.MustCompile(":443$"))).
	HandleConnect(goproxy.AlwaysReject)

func (FuncHttpsHandler) HandleConnect

func (f FuncHttpsHandler) HandleConnect(host string, ctx *ProxyCtx) (*ConnectAction, string)

FuncHttpsHandler should implement the RespHandler interface

type FuncReqHandler

type FuncReqHandler func(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response)

A wrapper that would convert a function to a ReqHandler interface type

func (FuncReqHandler) Handle

func (f FuncReqHandler) Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response)

FuncReqHandler.Handle(req,ctx) <=> FuncReqHandler(req,ctx)

type FuncRespHandler

type FuncRespHandler func(resp *http.Response, ctx *ProxyCtx) *http.Response

A wrapper that would convert a function to a RespHandler interface type

func (FuncRespHandler) Handle

func (f FuncRespHandler) Handle(resp *http.Response, ctx *ProxyCtx) *http.Response

FuncRespHandler.Handle(req,ctx) <=> FuncRespHandler(req,ctx)

type HttpsHandler

type HttpsHandler interface {
	HandleConnect(req string, ctx *ProxyCtx) (*ConnectAction, string)
}

When a client send a CONNECT request to a host, the request is filtered through all the HttpsHandlers the proxy has, and if one returns true, the connection is sniffed using Man in the Middle attack. That is, the proxy will create a TLS connection with the client, another TLS connection with the destination the client wished to connect to, and would send back and forth all messages from the server to the client and vice versa. The request and responses sent in this Man In the Middle channel are filtered through th eusual flow (request and response filtered through the ReqHanlders and RespHandlers)

type ProxyConds

type ProxyConds struct {
	// contains filtered or unexported fields
}

ProxyConds is used to aggregate RespConditions for a ProxyHttpServer. Upon calling ProxyConds.Do, it will register a RespHandler that would handle the HTTP response from remote server if all conditions on the HTTP response are met.

func (*ProxyConds) Do

func (pcond *ProxyConds) Do(h RespHandler)

ProxyConds.Do will register the RespHandler on the proxy, h.Handle(resp,ctx) will be called on every request that matches the conditions aggregated in pcond.

func (*ProxyConds) DoFunc

func (pcond *ProxyConds) DoFunc(f func(resp *http.Response, ctx *ProxyCtx) *http.Response)

ProxyConds.DoFunc is equivalent to proxy.OnResponse().Do(FuncRespHandler(f))

type ProxyCtx

type ProxyCtx struct {
	// Will contain the client request from the proxy
	Req *http.Request
	// Will contain the remote server's response (if available. nil if the request wasn't send yet)
	Resp      *http.Response
	RoundTrip *transport.RoundTripDetails
	// will contain the recent error that occured while trying to send receive or parse traffic
	Error error
	// A handle for the user to keep data in the context, from the call of ReqHandler to the
	// call of RespHandler
	UserData interface{}
	// Will connect a request to a response
	Session int64
	// contains filtered or unexported fields
}

ProxyCtx is the Proxy context, contains useful information about every request. It is passed to every user function. Also used as a logger.

func (*ProxyCtx) Charset

func (ctx *ProxyCtx) Charset() string

Will try to infer the character set of the request from the headers. Returns the empty string if we don't know which character set it used. Currently it will look for charset=<charset> in the Content-Type header of the request.

func (*ProxyCtx) Logf

func (ctx *ProxyCtx) Logf(msg string, argv ...interface{})

Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter This message will be printed only if the Verbose field of the ProxyHttpServer is set to true

proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) *http.Request{
	nr := atomic.AddInt32(&counter,1)
	ctx.Printf("So far %d requests",nr)
	return r
})

func (*ProxyCtx) Warnf

func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{})

Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter This message will always be printed.

proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) *http.Request{
	f,err := os.OpenFile(cachedContent)
	if err != nil {
		ctx.Warnf("error open file %v: %v",cachedContent,err)
		return r
	}
	return r
})

type ProxyHttpServer

type ProxyHttpServer struct {
	// setting Verbose to true will log information on each request sent to the proxy
	Verbose bool
	Logger  *log.Logger
	// contains filtered or unexported fields
}

The basic proxy type. Implements http.Handler.

func NewProxyHttpServer

func NewProxyHttpServer() *ProxyHttpServer

New proxy server, logs to StdErr by default

func (*ProxyHttpServer) OnRequest

func (proxy *ProxyHttpServer) OnRequest(conds ...ReqCondition) *ReqProxyConds

ProxyHttpServer.OnRequest Will return a temporary ReqProxyConds struct, aggregating the given condtions. You will use the ReqProxyConds struct to register a ReqHandler, that would filter the request, only if all the given ReqCondition matched. Typical usage:

proxy.OnRequest(UrlIs("example.com/foo"),UrlMatches(regexp.MustParse(`.*\.exampl.\com\./.*`)).Do(...)

func (*ProxyHttpServer) OnResponse

func (proxy *ProxyHttpServer) OnResponse(conds ...RespCondition) *ProxyConds

OnResponse is used when adding a response-filter to the HTTP proxy, usual pattern is

proxy.OnResponse(cond1,cond2).Do(handler) // handler.Handle(resp,ctx) will be used
			// if cond1.HandleResp(resp) && cond2.HandleResp(resp)

func (*ProxyHttpServer) ServeHTTP

func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

Standard net/http function. Shouldn't be used directly, http.Serve will use it.

type ReqCondition

type ReqCondition interface {
	RespCondition
	HandleReq(req *http.Request, ctx *ProxyCtx) bool
}

ReqCondition.HandleReq will decide whether or not to use the ReqHandler on an HTTP request before sending it to the remote server

func SrcIpIs

func SrcIpIs(ip string) ReqCondition

SrcIpIs returns a ReqCondtion testing wether the source IP of the request is the given string

type ReqConditionFunc

type ReqConditionFunc func(req *http.Request, ctx *ProxyCtx) bool

ReqConditionFunc.HandleReq(req,ctx) <=> ReqConditionFunc(req,ctx)

var IsLocalHost ReqConditionFunc = func(req *http.Request, ctx *ProxyCtx) bool {
	return req.URL.Host == "::1" ||
		req.URL.Host == "0:0:0:0:0:0:0:1" ||
		localHostIpv4.MatchString(req.URL.Host) ||
		req.URL.Host == "localhost"
}

IsLocalHost checks whether the destination host is explicitly local host (buggy, there can be IPv6 addresses it doesn't catch)

func DstHostIs

func DstHostIs(host string) ReqConditionFunc

DstHostIs returns a ReqCondtion testing wether the host in the request url is the given string

func Not

Not returns a ReqCondtion negating the given ReqCondition

func ReqHostIs

func ReqHostIs(hosts ...string) ReqConditionFunc

ReqHostIs returns a ReqCondition, testing whether the host to which the request is directed to equal to one of the given strings

func ReqHostMatches

func ReqHostMatches(regexps ...*regexp.Regexp) ReqConditionFunc

ReqHostMatches returns a ReqCondition, testing whether the host to which the request was directed to matches any of the given regular expressions.

func UrlHasPrefix

func UrlHasPrefix(prefix string) ReqConditionFunc

UrlHasPrefix returns a ReqCondtion checking wether the destination URL the proxy client has requested has the given prefix, with or without the host. For example UrlHasPrefix("host/x") will match requests of the form 'GET host/x', and will match requests to url 'http://host/x'

func UrlIs

func UrlIs(urls ...string) ReqConditionFunc

UrlIs returns a ReqCondition, testing whether or not the request URL is one of the given strings with or without the host prefix. UrlIs("google.com/","foo") will match requests 'GET /' to 'google.com', requests `'GET google.com/' to any host, and requests of the form 'GET foo'.

func UrlMatches

func UrlMatches(re *regexp.Regexp) ReqConditionFunc

UrlMatches returns a ReqCondition testing whether the destination URL of the request matches the given regexp, with or without prefix

func (ReqConditionFunc) HandleReq

func (c ReqConditionFunc) HandleReq(req *http.Request, ctx *ProxyCtx) bool

func (ReqConditionFunc) HandleResp

func (c ReqConditionFunc) HandleResp(resp *http.Response, ctx *ProxyCtx) bool

RespConditionFunc cannot test requests. It only satisfies ReqCondition interface so that RespCondition and ReqCondition will be of the same type.

type ReqHandler

type ReqHandler interface {
	Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response)
}

ReqHandler will "tamper" with the request coming to the proxy server If Handle returns req,nil the proxy will send the returned request to the destination server. If it returns nil,resp the proxy will skip sending any requests, and will simply return the response `resp` to the client.

type ReqProxyConds

type ReqProxyConds struct {
	// contains filtered or unexported fields
}

ReqProxyConds aggregate ReqConditions for a ProxyHttpServer. Upon calling Do, it will register a ReqHandler that would handle the request if all conditions on the HTTP request are met.

func (*ReqProxyConds) Do

func (pcond *ReqProxyConds) Do(h ReqHandler)

ReqProxyConds.Do will register the ReqHandler on the proxy, the ReqHandler will handle the HTTP request if all the conditions aggregated in the ReqProxyConds are met. Typical usage:

proxy.OnRequest().Do(handler) // will call handler.Handle(req,ctx) on every request to the proxy
proxy.OnRequest(cond1,cond2).Do(handler)
// given request to the proxy, will test if cond1.HandleReq(req,ctx) && cond2.HandleReq(req,ctx) are true
// if they are, will call handler.Handle(req,ctx)

func (*ReqProxyConds) DoFunc

func (pcond *ReqProxyConds) DoFunc(f func(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response))

DoFunc is equivalent to proxy.OnRequest().Do(FuncReqHandler(f))

func (*ReqProxyConds) HandleConnect

func (pcond *ReqProxyConds) HandleConnect(h HttpsHandler)

HandleConnect is used when proxy receives an HTTP CONNECT request, it'll then use the HttpsHandler to determine what should it do with this request. The handler returns a ConnectAction struct, the Action field in the ConnectAction struct returned will determine what to do with this request. ConnectAccept will simply accept the request forwarding all bytes from the client to the remote host, ConnectReject will close the connection with the client, and ConnectMitm, will assume the underlying connection is an HTTPS connection, and will use Man in the Middle attack to eavesdrop the connection. All regular handler will be active on this eavesdropped connection. The ConnectAction struct contains possible tlsConfig that will be used for eavesdropping. If nil, the proxy will use the default tls configuration.

proxy.OnRequest().HandleConnect(goproxy.AlwaysReject) // rejects all CONNECT requests

func (*ReqProxyConds) HandleConnectFunc

func (pcond *ReqProxyConds) HandleConnectFunc(f func(host string, ctx *ProxyCtx) (*ConnectAction, string))

HandleConnectFunc is equivalent to HandleConnect, for example, accepting CONNECT request if they contain a password in header

io.WriteString(h,password)
passHash := h.Sum(nil)
proxy.OnRequest().HandleConnectFunc(func(host string, ctx *ProxyCtx) (*ConnectAction, string) {
	c := sha1.New()
	io.WriteString(c,ctx.Req.Header.Get("X-GoProxy-Auth"))
	if c.Sum(nil) == passHash {
		return OkConnect, host
	}
	return RejectConnect, host
})

type RespCondition

type RespCondition interface {
	HandleResp(resp *http.Response, ctx *ProxyCtx) bool
}

ReqCondition.HandleReq will decide whether or not to use the RespHandler on an HTTP response before sending it to the proxy client

func ContentTypeIs

func ContentTypeIs(typ string, types ...string) RespCondition

ContentTypeIs returns a RespCondition testing whether the HTTP response has Content-Type header equal to one of the given strings.

type RespConditionFunc

type RespConditionFunc func(resp *http.Response, ctx *ProxyCtx) bool

RespConditionFunc.HandleResp(resp,ctx) <=> RespConditionFunc(resp,ctx)

func (RespConditionFunc) HandleResp

func (c RespConditionFunc) HandleResp(resp *http.Response, ctx *ProxyCtx) bool

type RespHandler

type RespHandler interface {
	Handle(resp *http.Response, ctx *ProxyCtx) *http.Response
}

after the proxy have sent the request to the destination server, it will "filter" the response through the RespHandlers it has. The proxy server will send to the client the response returned by the RespHandler. In case of error, resp will be nil, and ctx.RoundTrip.Error will contain the error

func HandleBytes

func HandleBytes(f func(b []byte, ctx *ProxyCtx) []byte) RespHandler

HandleBytes will return a RespHandler that read the entire body of the request to a byte array in memory, would run the user supplied f function on the byte arra, and will replace the body of the original response with the resulting byte array.

Directories

Path Synopsis
examples
ext
html
extension to goproxy that will allow you to easily filter web browser related content.
extension to goproxy that will allow you to easily filter web browser related content.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL