package proxy
import (
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/sirupsen/logrus"
)
type HTTPProxy struct {
name string
endpoints EndpointList
lb LoadBalance
client *http.Client
}
func (h *HTTPProxy) Proxy(w http.ResponseWriter, r *http.Request) {
endpoint := h.lb.Select(r, h.endpoints)
endURL, err := url.Parse(endpoint.GetHTTPAddr())
if err != nil {
logrus.Errorf("parse endpoint url error,%s", err.Error())
w.WriteHeader(502)
return
}
if endURL.Scheme == "" {
endURL.Scheme = "http"
}
proxy := httputil.NewSingleHostReverseProxy(endURL)
proxy.ServeHTTP(w, r)
}
func (h *HTTPProxy) UpdateEndpoints(endpoints ...string) {
ends := []string{}
for _, end := range endpoints {
if kv := strings.Split(end, "=>"); len(kv) > 1 {
ends = append(ends, kv[1])
} else {
ends = append(ends, end)
}
}
h.endpoints = CreateEndpoints(ends)
}
func (h *HTTPProxy) Do(r *http.Request) (*http.Response, error) {
endpoint := h.lb.Select(r, h.endpoints)
if strings.HasPrefix(endpoint.String(), "http") {
r.URL.Host = strings.Replace(endpoint.String(), "http://", "", 1)
} else {
r.URL.Host = endpoint.String()
}
r.URL.Scheme = "http"
return h.client.Do(r)
}
func createHTTPProxy(name string, endpoints []string, lb LoadBalance) *HTTPProxy {
ends := []string{}
for _, end := range endpoints {
if kv := strings.Split(end, "=>"); len(kv) > 1 {
ends = append(ends, kv[1])
} else {
ends = append(ends, end)
}
}
if lb == nil {
lb = NewRoundRobin()
}
timeout, _ := strconv.Atoi(os.Getenv("PROXY_TIMEOUT"))
if timeout == 0 {
timeout = 10
}
var netTransport = &http.Transport{
Dial: (&net.Dialer{
Timeout: 5 * time.Second,
}).Dial,
TLSHandshakeTimeout: 5 * time.Second,
}
client := &http.Client{
Transport: netTransport,
Timeout: time.Second * time.Duration(timeout),
}
return &HTTPProxy{name, CreateEndpoints(ends), lb, client}
}