fix: add backgroundRead for plain http inbound (#952)

https://github.com/golang/go/blob/go1.21.5/src/net/http/server.go#L682
This commit is contained in:
hunshcn 2024-01-02 13:45:40 +08:00 committed by GitHub
parent 1d3e9f4889
commit 4ee267ca7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,10 +1,14 @@
package http
import (
"context"
"fmt"
"io"
"net"
"net/http"
"strings"
"sync"
_ "unsafe"
"github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/common/lru"
@ -14,9 +18,18 @@ import (
"github.com/metacubex/mihomo/log"
)
//go:linkname registerOnHitEOF net/http.registerOnHitEOF
func registerOnHitEOF(rc io.ReadCloser, fn func())
//go:linkname requestBodyRemains net/http.requestBodyRemains
func requestBodyRemains(rc io.ReadCloser) bool
func HandleConn(c net.Conn, tunnel C.Tunnel, cache *lru.LruCache[string, bool], additions ...inbound.Addition) {
client := newClient(c, tunnel, additions...)
defer client.CloseIdleConnections()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
peekMutex := sync.Mutex{}
conn := N.NewBufferedConn(c)
@ -24,7 +37,9 @@ func HandleConn(c net.Conn, tunnel C.Tunnel, cache *lru.LruCache[string, bool],
trusted := cache == nil // disable authenticate if lru is nil
for keepAlive {
peekMutex.Lock()
request, err := ReadRequest(conn.Reader())
peekMutex.Unlock()
if err != nil {
break
}
@ -72,6 +87,23 @@ func HandleConn(c net.Conn, tunnel C.Tunnel, cache *lru.LruCache[string, bool],
if request.URL.Scheme == "" || request.URL.Host == "" {
resp = responseWith(request, http.StatusBadRequest)
} else {
request = request.WithContext(ctx)
startBackgroundRead := func() {
go func() {
peekMutex.Lock()
defer peekMutex.Unlock()
_, err := conn.Peek(1)
if err != nil {
cancel()
}
}()
}
if requestBodyRemains(request.Body) {
registerOnHitEOF(request.Body, startBackgroundRead)
} else {
startBackgroundRead()
}
resp, err = client.Do(request)
if err != nil {
resp = responseWith(request, http.StatusBadGateway)