mirror of
https://github.com/kemko/reproxy.git
synced 2026-01-01 15:55:49 +03:00
don't add dbl headers for X-Forwarded-Proto and X-Forwarded-Proto #172
This commit is contained in:
@@ -213,8 +213,8 @@ func (h *Http) proxyHandler() http.HandlerFunc {
|
|||||||
keepHost := ctx.Value(ctxKeepHost).(bool)
|
keepHost := ctx.Value(ctxKeepHost).(bool)
|
||||||
r.Header.Add("X-Forwarded-Host", r.Host)
|
r.Header.Add("X-Forwarded-Host", r.Host)
|
||||||
if h.SSLConfig.SSLMode == SSLAuto || h.SSLConfig.SSLMode == SSLStatic {
|
if h.SSLConfig.SSLMode == SSLAuto || h.SSLConfig.SSLMode == SSLStatic {
|
||||||
r.Header.Add("X-Forwarded-Proto", "https")
|
h.setHeaderIfNotExists(r, "X-Forwarded-Proto", "https")
|
||||||
r.Header.Add("X-Forwarded-Port", "443")
|
h.setHeaderIfNotExists(r, "X-Forwarded-Port", "443")
|
||||||
}
|
}
|
||||||
r.URL.Path = uu.Path
|
r.URL.Path = uu.Path
|
||||||
r.URL.Host = uu.Host
|
r.URL.Host = uu.Host
|
||||||
@@ -466,3 +466,9 @@ func (h *Http) discoveredServers(ctx context.Context, interval time.Duration) (s
|
|||||||
}
|
}
|
||||||
return servers
|
return servers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Http) setHeaderIfNotExists(r *http.Request, key, value string) {
|
||||||
|
if _, ok := r.Header[key]; !ok {
|
||||||
|
r.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -120,6 +122,111 @@ func TestHttp_Do(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHttp_DoWithSSL(t *testing.T) {
|
||||||
|
port := rand.Intn(10000) + 40000
|
||||||
|
h := Http{Timeouts: Timeouts{ResponseHeader: 200 * time.Millisecond}, Address: fmt.Sprintf("localhost:%d", port),
|
||||||
|
AccessLog: io.Discard, Signature: true, ProxyHeaders: []string{"hh1:vv1", "hh2:vv2"}, StdOutEnabled: true,
|
||||||
|
Reporter: &ErrorReporter{Nice: true},
|
||||||
|
SSLConfig: SSLConfig{SSLMode: SSLStatic, Cert: "testdata/localhost.crt", Key: "testdata/localhost.key"}, Insecure: true,
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
ds := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
t.Logf("req: %v", r)
|
||||||
|
w.Header().Add("h1", "v1")
|
||||||
|
require.Equal(t, "127.0.0.1", r.Header.Get("X-Real-IP"))
|
||||||
|
require.Equal(t, "127.0.0.1", r.Header.Get("X-Forwarded-For"))
|
||||||
|
require.Equal(t, "https", r.Header.Get("X-Forwarded-Proto")) // ssl auto only
|
||||||
|
require.Equal(t, "443", r.Header.Get("X-Forwarded-Port"))
|
||||||
|
fmt.Fprintf(w, "response %s", r.URL.String())
|
||||||
|
}))
|
||||||
|
|
||||||
|
svc := discovery.NewService([]discovery.Provider{
|
||||||
|
&provider.Static{Rules: []string{
|
||||||
|
"localhost,^/api/(.*)," + strings.Replace(ds.URL, "127.0.0.1", "localhost", 1) + "/123/$1,",
|
||||||
|
"127.0.0.1,^/api/(.*)," + strings.Replace(ds.URL, "127.0.0.1", "localhost", 1) + "/567/$1,",
|
||||||
|
},
|
||||||
|
}}, time.Millisecond*10)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_ = svc.Run(context.Background())
|
||||||
|
}()
|
||||||
|
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
h.Matcher = svc
|
||||||
|
h.Metrics = mgmt.NewMetrics()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_ = h.Run(ctx)
|
||||||
|
}()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
|
client := http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("to localhost, good", func(t *testing.T) {
|
||||||
|
req, err := http.NewRequest("GET", "https://localhost:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||||
|
require.NoError(t, err)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
t.Logf("%+v", resp.Header)
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "response /123/something", string(body))
|
||||||
|
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||||
|
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||||
|
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||||
|
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("to localhost, request with X-Forwarded-Proto and X-Forwarded-Port", func(t *testing.T) {
|
||||||
|
req, err := http.NewRequest("GET", "https://localhost:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||||
|
req.Header.Set("X-Forwarded-Proto", "https")
|
||||||
|
req.Header.Set("X-Forwarded-Port", "443")
|
||||||
|
require.NoError(t, err)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
t.Logf("%+v", resp.Header)
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "response /123/something", string(body))
|
||||||
|
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||||
|
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||||
|
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||||
|
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("to 127.0.0.1", func(t *testing.T) {
|
||||||
|
req, err := http.NewRequest("GET", "https://127.0.0.1:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||||
|
req.Header.Set("X-Forwarded-Proto", "https")
|
||||||
|
req.Header.Set("X-Forwarded-Port", "443")
|
||||||
|
require.NoError(t, err)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
t.Logf("%+v", resp.Header)
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "response /567/something", string(body))
|
||||||
|
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||||
|
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||||
|
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||||
|
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestHttp_DoWithAssets(t *testing.T) {
|
func TestHttp_DoWithAssets(t *testing.T) {
|
||||||
port := rand.Intn(10000) + 40000
|
port := rand.Intn(10000) + 40000
|
||||||
cc := NewCacheControl(time.Hour * 12)
|
cc := NewCacheControl(time.Hour * 12)
|
||||||
|
|||||||
37
app/proxy/testdata/localhost.crt
vendored
37
app/proxy/testdata/localhost.crt
vendored
@@ -1,18 +1,21 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
GHmkcX4ABMze6SN7cWFpgeIvy1mxKfMoZw==
|
sIqn3Ph3y6AcnyrkobCYOPho4dZMTsuSPfa9WRuFdvpUuZcn9JlvzlPZeYs6ba32
|
||||||
-----END CERTIFICATE-----
|
wZfGBu6We26u89dcUKstKLEWZOI6rvTwViDiNafpnQc2JmP8U27wkyQe0uRuwUUY
|
||||||
|
nLlB44QmWWHgct2YJz7wIJ0R9LQB32rhvLvkDnpl2VRA87xl8Q4z6yGfZVSzkRtq
|
||||||
|
2K8HX+VuCB3NB61tC+eYbNEehkcdfJmuXzO/fLcoMWKEH5Q1ExmPMn+BKQ==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
54
app/proxy/testdata/localhost.key
vendored
54
app/proxy/testdata/localhost.key
vendored
@@ -1,28 +1,28 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
ON1xMW7NBrs9xvcjhBVgtn6r
|
oJdJyZA2raAm/gaOyTIqDz0=
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
Reference in New Issue
Block a user