mirror of
https://github.com/fatedier/frp.git
synced 2026-07-23 12:09:19 +08:00
server: drop HTTP/1.1 h2c upgrade handling (#5436)
Use net/http Server.Protocols and the merged golib listener path instead of the deprecated h2c handler. Keep HTTP/1.1 and cleartext HTTP/2 prior-knowledge support, while intentionally dropping HTTP/1.1 Upgrade: h2c.
This commit is contained in:
@@ -28,8 +28,6 @@ import (
|
||||
|
||||
libio "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
|
||||
httppkg "github.com/fatedier/frp/pkg/util/http"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
@@ -139,7 +137,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
||||
_, _ = rw.Write(getNotFoundPageContent())
|
||||
},
|
||||
}
|
||||
rp.proxy = h2c.NewHandler(proxy, &http2.Server{})
|
||||
rp.proxy = proxy
|
||||
return rp
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,94 @@
|
||||
package vhost
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
httppkg "github.com/fatedier/frp/pkg/util/http"
|
||||
)
|
||||
|
||||
func TestHTTPServerProtocols(t *testing.T) {
|
||||
rp := NewHTTPReverseProxy(HTTPReverseProxyOptions{}, NewRouters())
|
||||
protocols := new(http.Protocols)
|
||||
protocols.SetHTTP1(true)
|
||||
protocols.SetUnencryptedHTTP2(true)
|
||||
server := &http.Server{
|
||||
Handler: rp,
|
||||
ReadHeaderTimeout: time.Second,
|
||||
Protocols: protocols,
|
||||
}
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
|
||||
serveErr := make(chan error, 1)
|
||||
go func() {
|
||||
serveErr <- server.Serve(listener)
|
||||
}()
|
||||
defer func() {
|
||||
require.NoError(t, server.Close())
|
||||
require.ErrorIs(t, <-serveErr, http.ErrServerClosed)
|
||||
}()
|
||||
|
||||
require.True(t, server.Protocols.HTTP1())
|
||||
require.True(t, server.Protocols.UnencryptedHTTP2())
|
||||
|
||||
t.Run("HTTP/1.1", func(t *testing.T) {
|
||||
transport := &http.Transport{Protocols: httpProtocols(true, false)}
|
||||
defer transport.CloseIdleConnections()
|
||||
client := &http.Client{Transport: transport}
|
||||
response, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
require.NoError(t, err)
|
||||
defer response.Body.Close()
|
||||
|
||||
require.Equal(t, "HTTP/1.1", response.Proto)
|
||||
require.Equal(t, http.StatusNotFound, response.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("HTTP/2 prior knowledge", func(t *testing.T) {
|
||||
transport := &http.Transport{Protocols: httpProtocols(false, true)}
|
||||
defer transport.CloseIdleConnections()
|
||||
client := &http.Client{Transport: transport}
|
||||
response, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
require.NoError(t, err)
|
||||
defer response.Body.Close()
|
||||
|
||||
require.Equal(t, "HTTP/2.0", response.Proto)
|
||||
require.Equal(t, http.StatusNotFound, response.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("HTTP/1.1 Upgrade h2c", func(t *testing.T) {
|
||||
conn, err := net.Dial("tcp", listener.Addr().String())
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
_, err = fmt.Fprintf(conn,
|
||||
"GET / HTTP/1.1\r\nHost: %s\r\n"+
|
||||
"Connection: Upgrade, HTTP2-Settings\r\nUpgrade: h2c\r\n"+
|
||||
"HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA\r\n\r\n",
|
||||
listener.Addr())
|
||||
require.NoError(t, err)
|
||||
response, err := http.ReadResponse(bufio.NewReader(conn), nil)
|
||||
require.NoError(t, err)
|
||||
defer response.Body.Close()
|
||||
|
||||
require.NotEqual(t, http.StatusSwitchingProtocols, response.StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
func httpProtocols(http1, unencryptedHTTP2 bool) *http.Protocols {
|
||||
protocols := new(http.Protocols)
|
||||
protocols.SetHTTP1(http1)
|
||||
protocols.SetUnencryptedHTTP2(unencryptedHTTP2)
|
||||
return protocols
|
||||
}
|
||||
|
||||
func TestCheckRouteAuthByRequest(t *testing.T) {
|
||||
rc := &RouteConfig{
|
||||
Username: "alice",
|
||||
|
||||
Reference in New Issue
Block a user