mirror of
https://github.com/rclone/rclone.git
synced 2026-05-18 13:52:30 -04:00
lib/http: Add HTTP/2 cleartext support in server configuration
Enable HTTP/2 cleartext support for non-TLS listeners.
This commit is contained in:
@@ -23,6 +23,8 @@ import (
|
||||
"github.com/rclone/rclone/lib/atexit"
|
||||
sdActivation "github.com/rclone/rclone/lib/sdactivation"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
)
|
||||
|
||||
// Help returns text describing the http server to add to the command
|
||||
@@ -61,6 +63,12 @@ identically.
|
||||
|
||||
` + "`--{{ .Prefix }}disable-zip`" + ` may be set to disable the zipping download option.
|
||||
|
||||
#### Protocol
|
||||
|
||||
The server supports HTTP/1.1 and HTTP/2. HTTP/2 is used automatically
|
||||
for TLS connections. For non-TLS connections, HTTP/2 cleartext (h2c)
|
||||
is supported, allowing HTTP/2 without encryption.
|
||||
|
||||
#### TLS (SSL)
|
||||
|
||||
By default this will serve over http. If you want you can serve over
|
||||
@@ -273,11 +281,18 @@ func newInstance(ctx context.Context, s *Server, listener net.Listener, tlsCfg *
|
||||
listener = tls.NewListener(listener, tlsCfg)
|
||||
}
|
||||
|
||||
var handler http.Handler = s.mux
|
||||
// Enable h2c (HTTP/2 cleartext) for non-TLS listeners
|
||||
if tlsCfg == nil {
|
||||
h2s := &http2.Server{}
|
||||
handler = h2c.NewHandler(s.mux, h2s)
|
||||
}
|
||||
|
||||
return &instance{
|
||||
url: url,
|
||||
listener: listener,
|
||||
httpServer: &http.Server{
|
||||
Handler: s.mux,
|
||||
Handler: handler,
|
||||
ReadTimeout: time.Duration(s.cfg.ServerReadTimeout),
|
||||
WriteTimeout: time.Duration(s.cfg.ServerWriteTimeout),
|
||||
MaxHeaderBytes: s.cfg.MaxHeaderBytes,
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
func testEmptyHandler() http.Handler {
|
||||
@@ -550,6 +551,49 @@ func TestNewServerTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestH2CServer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := DefaultCfg()
|
||||
cfg.ListenAddr = []string{"127.0.0.1:0"}
|
||||
|
||||
s, err := NewServer(ctx, WithConfig(cfg))
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
require.NoError(t, s.Shutdown())
|
||||
}()
|
||||
|
||||
expected := []byte("h2c-test-response")
|
||||
s.Router().Mount("/", testEchoHandler(expected))
|
||||
s.Serve()
|
||||
|
||||
url := testGetServerURL(t, s)
|
||||
require.True(t, strings.HasPrefix(url, "http://"), "url should have http scheme (no TLS)")
|
||||
|
||||
// Create an HTTP/2 cleartext client
|
||||
client := &http.Client{
|
||||
Transport: &http2.Transport{
|
||||
AllowHTTP: true,
|
||||
DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
|
||||
return net.Dial(network, addr)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
require.Equal(t, 2, resp.ProtoMajor, "response should be HTTP/2")
|
||||
testExpectRespBody(t, resp, expected)
|
||||
}
|
||||
|
||||
func TestHelpPrefixServer(t *testing.T) {
|
||||
// This test assumes template variables are placed correctly.
|
||||
const testPrefix = "server-help-test"
|
||||
|
||||
Reference in New Issue
Block a user