Skip to content

Commit 5943808

Browse files
chungthuangnmldiegues
authored andcommitted
TUN-3889: Move host header override logic to httpService
1 parent ed57ee6 commit 5943808

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

ingress/origin_proxy.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,20 @@ func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
3737
// Rewrite the request URL so that it goes to the origin service.
3838
req.URL.Host = o.url.Host
3939
req.URL.Scheme = o.url.Scheme
40+
if o.hostHeader != "" {
41+
// For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
42+
req.Host = o.hostHeader
43+
}
4044
return o.transport.RoundTrip(req)
4145
}
4246

4347
func (o *httpService) EstablishConnection(req *http.Request) (OriginConnection, *http.Response, error) {
4448
req.URL.Host = o.url.Host
4549
req.URL.Scheme = websocket.ChangeRequestScheme(o.url)
50+
if o.hostHeader != "" {
51+
// For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
52+
req.Host = o.hostHeader
53+
}
4654
return newWSConnection(o.transport, req)
4755
}
4856

ingress/origin_proxy_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package ingress
22

33
import (
4+
"context"
45
"net/http"
6+
"net/http/httptest"
7+
"net/url"
8+
"sync"
59
"testing"
610

711
"github.com/cloudflare/cloudflared/h2mux"
12+
"github.com/cloudflare/cloudflared/websocket"
13+
"github.com/rs/zerolog"
814
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
916
)
1017

1118
func TestBridgeServiceDestination(t *testing.T) {
@@ -105,3 +112,47 @@ func TestBridgeServiceDestination(t *testing.T) {
105112
}
106113
}
107114
}
115+
116+
func TestHTTPServiceHostHeaderOverride(t *testing.T) {
117+
cfg := OriginRequestConfig{
118+
HTTPHostHeader: t.Name(),
119+
}
120+
handler := func(w http.ResponseWriter, r *http.Request) {
121+
require.Equal(t, r.Host, t.Name())
122+
if websocket.IsWebSocketUpgrade(r) {
123+
respHeaders := websocket.NewResponseHeader(r)
124+
for k, v := range respHeaders {
125+
w.Header().Set(k, v[0])
126+
}
127+
w.WriteHeader(http.StatusSwitchingProtocols)
128+
return
129+
}
130+
w.Write([]byte("ok"))
131+
}
132+
origin := httptest.NewServer(http.HandlerFunc(handler))
133+
defer origin.Close()
134+
135+
originURL, err := url.Parse(origin.URL)
136+
require.NoError(t, err)
137+
138+
httpService := &httpService{
139+
url: originURL,
140+
}
141+
var wg sync.WaitGroup
142+
log := zerolog.Nop()
143+
shutdownC := make(chan struct{})
144+
errC := make(chan error)
145+
require.NoError(t, httpService.start(&wg, &log, shutdownC, errC, cfg))
146+
147+
req, err := http.NewRequest(http.MethodGet, originURL.String(), nil)
148+
require.NoError(t, err)
149+
150+
resp, err := httpService.RoundTrip(req)
151+
require.NoError(t, err)
152+
require.Equal(t, http.StatusOK, resp.StatusCode)
153+
154+
req = req.Clone(context.Background())
155+
_, resp, err = httpService.EstablishConnection(req)
156+
require.NoError(t, err)
157+
require.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode)
158+
}

ingress/origin_service.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,17 @@ func (o *unixSocketPath) Dial(reqURL *url.URL, headers http.Header) (*gws.Conn,
5959
}
6060

6161
type httpService struct {
62-
url *url.URL
63-
transport *http.Transport
62+
url *url.URL
63+
hostHeader string
64+
transport *http.Transport
6465
}
6566

6667
func (o *httpService) start(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
6768
transport, err := newHTTPTransport(o, cfg, log)
6869
if err != nil {
6970
return err
7071
}
72+
o.hostHeader = cfg.HTTPHostHeader
7173
o.transport = transport
7274
return nil
7375
}

origin/proxy.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ func (p *proxy) Proxy(w connection.ResponseWriter, req *http.Request, sourceConn
8686
return nil
8787
}
8888

89-
if hostHeader := rule.Config.HTTPHostHeader; hostHeader != "" {
90-
req.Header.Set("Host", hostHeader)
91-
req.Host = hostHeader
92-
}
93-
9489
connectionProxy, ok := rule.Service.(ingress.StreamBasedOriginProxy)
9590
if !ok {
9691
p.log.Error().Msgf("%s is not a connection-oriented service", rule.Service)
@@ -125,11 +120,6 @@ func (p *proxy) proxyHTTP(w connection.ResponseWriter, req *http.Request, rule *
125120
// Request origin to keep connection alive to improve performance
126121
req.Header.Set("Connection", "keep-alive")
127122

128-
if hostHeader := rule.Config.HTTPHostHeader; hostHeader != "" {
129-
req.Header.Set("Host", hostHeader)
130-
req.Host = hostHeader
131-
}
132-
133123
httpService, ok := rule.Service.(ingress.HTTPOriginProxy)
134124
if !ok {
135125
p.log.Error().Msgf("%s is not a http service", rule.Service)

0 commit comments

Comments
 (0)