Package httpproxy provides a customizable HTTP proxy; supports HTTP, HTTPS through CONNECT. And also provides HTTPS connection using "Man in the Middle" style attack.
It's easy to use. httpproxy.Proxy implements Handler interface of net/http
package to offer http.ListenAndServe function.
go get -u github.com/go-httpproxy/httpproxy
# or
go get -u gopkg.in/httpproxy.v1Library has two significant structs: Proxy and Context.
// Proxy defines parameters for running an HTTP Proxy. It implements// http.Handler interface for ListenAndServe function. If you need, you must// set Proxy struct before handling requests.typeProxystruct {
// Session number of last proxy request.SessionNoint64// RoundTripper interface to obtain remote response.// By default, it uses &http.Transport{}.Rt http.RoundTripper// Certificate key pair.Ca tls.Certificate// User data to use free.UserDatainterface{}
// Error callback.OnErrorfunc(ctx*Context, wherestring, err*Error, opErrerror)
// Accept callback. It greets proxy request like ServeHTTP function of// http.Handler.// If it returns true, stops processing proxy request.OnAcceptfunc(ctx*Context, w http.ResponseWriter, r*http.Request) bool// Auth callback. If you need authentication, set this callback.// If it returns true, authentication succeeded.OnAuthfunc(ctx*Context, authTypestring, userstring, passstring) bool// Connect callback. It sets connect action and new host.// If len(newhost) > 0, host changes.OnConnectfunc(ctx*Context, hoststring) (ConnectActionConnectAction,
newHoststring)
// Request callback. It greets remote request.// If it returns non-nil response, stops processing remote request.OnRequestfunc(ctx*Context, req*http.Request) (resp*http.Response)
// Response callback. It greets remote response.// Remote response sends after this callback.OnResponsefunc(ctx*Context, req*http.Request, resp*http.Response)
// If ConnectAction is ConnectMitm, it sets chunked to Transfer-Encoding.// By default, true.MitmChunkedbool// HTTP Authentication type. If it's not specified (""), uses "Basic".// By default, "".AuthTypestring
}// Context keeps context of each proxy request.typeContextstruct {
// Pointer of Proxy struct handled this context.// It's using internally. Don't change in Context struct!Prx*Proxy// Session number of this context obtained from Proxy struct.SessionNoint64// Sub session number of processing remote connection.SubSessionNoint64// Original Proxy request.// It's using internally. Don't change in Context struct!Req*http.Request// Original Proxy request, if proxy request method is CONNECT.// It's using internally. Don't change in Context struct!ConnectReq*http.Request// Action of after the CONNECT, if proxy request method is CONNECT.// It's using internally. Don't change in Context struct!ConnectActionConnectAction// Remote host, if proxy request method is CONNECT.// It's using internally. Don't change in Context struct!ConnectHoststring// User data to use free.UserDatainterface{}
}For more examples, examples/
package main
import (
"log""net/http""github.com/go-httpproxy/httpproxy"
)
funcOnError(ctx*httpproxy.Context, wherestring,
err*httpproxy.Error, opErrerror) {
// Log errors.log.Printf("ERR: %s: %s [%s]", where, err, opErr)
}
funcOnAccept(ctx*httpproxy.Context, w http.ResponseWriter,
r*http.Request) bool {
// Handle local request has path "/info"ifr.Method=="GET"&&!r.URL.IsAbs() &&r.URL.Path=="/info" {
w.Write([]byte("This is go-httpproxy."))
returntrue
}
returnfalse
}
funcOnAuth(ctx*httpproxy.Context, authTypestring, userstring, passstring) bool {
// Auth test user.ifuser=="test"&&pass=="1234" {
returntrue
}
returnfalse
}
funcOnConnect(ctx*httpproxy.Context, hoststring) (
ConnectAction httpproxy.ConnectAction, newHoststring) {
// Apply "Man in the Middle" to all ssl connections. Never change host.returnhttpproxy.ConnectMitm, host
}
funcOnRequest(ctx*httpproxy.Context, req*http.Request) (
resp*http.Response) {
// Log proxying requests.log.Printf("INFO: Proxy: %s %s", req.Method, req.URL.String())
return
}
funcOnResponse(ctx*httpproxy.Context, req*http.Request,
resp*http.Response) {
// Add header "Via: go-httpproxy".resp.Header.Add("Via", "go-httpproxy")
}
funcmain() {
// Create a new proxy with default certificate pair.prx, _:=httpproxy.NewProxy()
// Set handlers.prx.OnError=OnErrorprx.OnAccept=OnAcceptprx.OnAuth=OnAuthprx.OnConnect=OnConnectprx.OnRequest=OnRequestprx.OnResponse=OnResponse// Listen...http.ListenAndServe(":8080", prx)
}