-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from go-httpproxy/develop
v1.1
- Loading branch information
Showing
8 changed files
with
433 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,186 @@ | ||
# go-httpproxy | ||
# A Go HTTP proxy library which has KISS principle | ||
|
||
## Introduction | ||
|
||
`github.com/go-httpproxy/httpproxy` repository provides an HTTP proxy library | ||
for Go (golang). | ||
|
||
The library is regular 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. | ||
|
||
### Keep it simple, stupid! | ||
|
||
> KISS is an acronym for "Keep it simple, stupid" as a design principle. The | ||
KISS principle states that most systems work best if they are kept simple rather | ||
than made complicated; therefore simplicity should be a key goal in design and | ||
unnecessary complexity should be avoided. [Wikipedia] | ||
|
||
## Usage | ||
|
||
Library has two significant structs: Proxy and Context. | ||
|
||
### Proxy struct | ||
|
||
```go | ||
// Proxy defines parameters for running an HTTP Proxy. It implements | ||
// http.Handler interface for ListenAndServe function. If you need, you must | ||
// fill Proxy struct before handling requests. | ||
type Proxy struct { | ||
// Session number of last proxy request. | ||
SessionNo int64 | ||
|
||
// 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. | ||
UserData interface{} | ||
|
||
// Error handler. | ||
OnError func(ctx *Context, when string, err *Error, opErr error) | ||
|
||
// Accept handler. It greets proxy request like ServeHTTP function of | ||
// http.Handler. | ||
// If it returns true, stops processing proxy request. | ||
OnAccept func(ctx *Context, w http.ResponseWriter, r *http.Request) bool | ||
|
||
// Auth handler. If you need authentication, set this handler. | ||
// If it returns true, authentication succeeded. | ||
OnAuth func(ctx *Context, user string, pass string) bool | ||
|
||
// Connect handler. It sets connect action and new host. | ||
// If len(newhost) > 0, host changes. | ||
OnConnect func(ctx *Context, host string) (ConnectAction ConnectAction, | ||
newHost string) | ||
|
||
// Request handler. It greets remote request. | ||
// If it returns non-nil response, stops processing remote request. | ||
OnRequest func(ctx *Context, req *http.Request) (resp *http.Response) | ||
|
||
// Response handler. It greets remote response. | ||
// Remote response sends after this handler. | ||
OnResponse func(ctx *Context, req *http.Request, resp *http.Response) | ||
|
||
// If ConnectAction is ConnectMitm, it sets chunked to Transfer-Encoding. | ||
// By default, it is true. | ||
MitmChunked bool | ||
} | ||
``` | ||
|
||
### Context struct | ||
|
||
```go | ||
// Context keeps context of each proxy request. | ||
type Context struct { | ||
// 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. | ||
SessionNo int64 | ||
|
||
// Sub session number of processing remote connection. | ||
SubSessionNo int64 | ||
|
||
// Action of after the CONNECT, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectAction ConnectAction | ||
|
||
// Proxy request, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectReq *http.Request | ||
|
||
// Remote host, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectHost string | ||
|
||
// User data to use free. | ||
UserData interface{} | ||
} | ||
``` | ||
|
||
### Demo code | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"log" | ||
"net/http" | ||
|
||
"github.com/go-httpproxy/httpproxy" | ||
) | ||
|
||
func OnError(ctx *httpproxy.Context, when string, | ||
err *httpproxy.Error, opErr error) { | ||
// Log errors. | ||
log.Printf("ERR: %s: %s [%s]", when, err, opErr) | ||
} | ||
|
||
func OnAccept(ctx *httpproxy.Context, w http.ResponseWriter, | ||
r *http.Request) bool { | ||
// Handle local request has path "/info" | ||
if r.Method == "GET" && !r.URL.IsAbs() && r.URL.Path == "/info" { | ||
w.Write([]byte("This is go-httpproxy.")) | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func OnAuth(ctx *httpproxy.Context, user string, pass string) bool { | ||
// Auth test user. | ||
if user == "test" && pass == "1234" { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func OnConnect(ctx *httpproxy.Context, host string) ( | ||
ConnectAction httpproxy.ConnectAction, newHost string) { | ||
// Apply "Man in the Middle" to all ssl connections. Never change host. | ||
return httpproxy.ConnectMitm, host | ||
} | ||
|
||
func OnRequest(ctx *httpproxy.Context, req *http.Request) ( | ||
resp *http.Response) { | ||
// Log proxying requests. | ||
log.Printf("INFO: Proxy: %s %s", req.Method, req.URL.String()) | ||
return | ||
} | ||
|
||
func OnResponse(ctx *httpproxy.Context, req *http.Request, | ||
resp *http.Response) { | ||
// Add header "Via: go-httpproxy". | ||
resp.Header.Add("Via", "go-httpproxy") | ||
} | ||
|
||
func main() { | ||
// Create a new proxy with default certificate pair. | ||
prx, _ := httpproxy.NewProxy() | ||
|
||
// Set handlers. | ||
prx.OnError = OnError | ||
prx.OnAccept = OnAccept | ||
prx.OnAuth = OnAuth | ||
prx.OnConnect = OnConnect | ||
prx.OnRequest = OnRequest | ||
prx.OnResponse = OnResponse | ||
|
||
// Listen... | ||
http.ListenAndServe(":8080", prx) | ||
} | ||
``` | ||
|
||
## GoDoc | ||
|
||
[https://godoc.org/github.com/go-httpproxy/httpproxy](https://godoc.org/github.com/go-httpproxy/httpproxy) | ||
|
||
## To-Do | ||
|
||
* GoDoc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,38 @@ | ||
package httpproxy | ||
|
||
import "net/http" | ||
import ( | ||
"bufio" | ||
"crypto/tls" | ||
"net/http" | ||
) | ||
|
||
// Context defines context of each proxy connection. | ||
// Context keeps context of each proxy request. | ||
type Context struct { | ||
Prx *Proxy | ||
SessionNo int64 | ||
// 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. | ||
SessionNo int64 | ||
|
||
// Sub session number of processing remote connection. | ||
SubSessionNo int64 | ||
|
||
// Action of after the CONNECT, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectAction ConnectAction | ||
ConnectReq *http.Request | ||
UserData interface{} | ||
|
||
// Proxy request, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectReq *http.Request | ||
|
||
// Remote host, if proxy request method is CONNECT. | ||
// It's using internally. Don't change in Context struct! | ||
ConnectHost string | ||
|
||
// User data to use free. | ||
UserData interface{} | ||
|
||
hijTLSConn *tls.Conn | ||
hijTLSReader *bufio.Reader | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.