72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package httpproxy
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
func (h *handler) handleHTTP(responseWriter http.ResponseWriter, request *http.Request) {
|
|
switch request.URL.Scheme {
|
|
case "http", "https":
|
|
default:
|
|
h.logger.Warn("Unsupported scheme %q", request.URL.Scheme)
|
|
http.Error(responseWriter, "unsupported scheme", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
request = request.WithContext(h.ctx)
|
|
|
|
request.RequestURI = ""
|
|
|
|
for _, key := range hopHeaders {
|
|
request.Header.Del(key)
|
|
}
|
|
|
|
if !h.stealth {
|
|
setForwardedHeaders(request)
|
|
}
|
|
|
|
response, err := h.client.Do(request)
|
|
if err != nil {
|
|
http.Error(responseWriter, "server error", http.StatusInternalServerError)
|
|
h.logger.Warn("cannot request %s for client %q: %s",
|
|
request.URL, request.RemoteAddr, err)
|
|
return
|
|
}
|
|
defer response.Body.Close()
|
|
if h.verbose {
|
|
h.logger.Info("%s %s %s %s", request.RemoteAddr, response.Status, request.Method, request.URL)
|
|
}
|
|
|
|
for _, key := range hopHeaders {
|
|
response.Header.Del(key)
|
|
}
|
|
|
|
targetHeaderPtr := responseWriter.Header()
|
|
for key, values := range response.Header {
|
|
for _, value := range values {
|
|
targetHeaderPtr.Add(key, value)
|
|
}
|
|
}
|
|
|
|
responseWriter.WriteHeader(response.StatusCode)
|
|
if _, err := io.Copy(responseWriter, response.Body); err != nil {
|
|
h.logger.Error("%s %s: body copy error: %s", request.RemoteAddr, request.URL, err)
|
|
}
|
|
}
|
|
|
|
func setForwardedHeaders(request *http.Request) {
|
|
clientIP, _, err := net.SplitHostPort(request.RemoteAddr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// keep existing proxy headers
|
|
if prior, ok := request.Header["X-Forwarded-For"]; ok {
|
|
clientIP = fmt.Sprintf("%s,%s", strings.Join(prior, ", "), clientIP)
|
|
}
|
|
request.Header.Set("X-Forwarded-For", clientIP)
|
|
}
|