mirror of
https://github.com/telanflow/mps.git
synced 2025-09-26 20:41:25 +08:00
test
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,3 +13,5 @@
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
.DS_Store
|
||||
.idea
|
||||
|
5
context.go
Normal file
5
context.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package mps
|
||||
|
||||
type ProxyContext struct {
|
||||
|
||||
}
|
7
examples/main.go
Normal file
7
examples/main.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
|
||||
|
||||
}
|
7
middleware.go
Normal file
7
middleware.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package mps
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Middleware func(req *http.Request, resp *http.Response)
|
||||
|
||||
type a http.HandlerFunc
|
122
proxy_server.go
Normal file
122
proxy_server.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package mps
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ProxyServer struct {
|
||||
middleware []Middleware
|
||||
Transport *http.Transport
|
||||
KeepHeader bool
|
||||
// KeepDestinationHeaders indicates the proxy should retain any headers present in the http.Response before proxying
|
||||
KeepDestinationHeaders bool
|
||||
}
|
||||
|
||||
func NewProxyServer() *ProxyServer {
|
||||
return &ProxyServer{
|
||||
middleware: nil,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProxyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodConnect {
|
||||
p.handlerHttps(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
p.handlerHttp(w, r)
|
||||
}
|
||||
|
||||
func (p *ProxyServer) handlerHttp(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
|
||||
if !p.KeepHeader {
|
||||
removeProxyHeaders(r)
|
||||
}
|
||||
|
||||
resp, err := p.Transport.RoundTrip(r)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
origBody := resp.Body
|
||||
defer origBody.Close()
|
||||
|
||||
// http.ResponseWriter will take care of filling the correct response length
|
||||
// Setting it now, might impose wrong value, contradicting the actual new
|
||||
// body the user returned.
|
||||
// We keep the original body to remove the header only if things changed.
|
||||
// This will prevent problems with HEAD requests where there's no body, yet,
|
||||
// the Content-Length header should be set.
|
||||
if origBody != resp.Body {
|
||||
resp.Header.Del("Content-Length")
|
||||
}
|
||||
copyHeaders(w.Header(), resp.Header, p.KeepDestinationHeaders)
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
io.Copy(w, resp.Body)
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
func (p *ProxyServer) handlerHttps(w http.ResponseWriter, r *http.Request) {
|
||||
hij, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Not a hijacker?", 500)
|
||||
return
|
||||
}
|
||||
|
||||
proxyClientConn, _, e := hij.Hijack()
|
||||
if e != nil {
|
||||
http.Error(w, "Cannot hijack connection " + e.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
func removeProxyHeaders(r *http.Request) {
|
||||
r.RequestURI = "" // this must be reset when serving a request with the client
|
||||
// If no Accept-Encoding header exists, Transport will add the headers it can accept
|
||||
// and would wrap the response body with the relevant reader.
|
||||
r.Header.Del("Accept-Encoding")
|
||||
// curl can add that, see
|
||||
// https://jdebp.eu./FGA/web-proxy-connection-header.html
|
||||
r.Header.Del("Proxy-Connection")
|
||||
r.Header.Del("Proxy-Authenticate")
|
||||
r.Header.Del("Proxy-Authorization")
|
||||
// Connection, Authenticate and Authorization are single hop Header:
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616.txt
|
||||
// 14.10 Connection
|
||||
// The Connection general-header field allows the sender to specify
|
||||
// options that are desired for that particular connection and MUST NOT
|
||||
// be communicated by proxies over further connections.
|
||||
r.Header.Del("Connection")
|
||||
}
|
||||
|
||||
func copyHeaders(dst, src http.Header, keepDestHeaders bool) {
|
||||
if !keepDestHeaders {
|
||||
for k := range dst {
|
||||
dst.Del(k)
|
||||
}
|
||||
}
|
||||
for k, vs := range src {
|
||||
for _, v := range vs {
|
||||
dst.Add(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isEof(r *bufio.Reader) bool {
|
||||
_, err := r.Peek(1)
|
||||
if err == io.EOF {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
9
proxy_server_test.go
Normal file
9
proxy_server_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package mps
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestProxyServer_ServeHTTP(t *testing.T) {
|
||||
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user