txthinking/brook · error
Invalid Request
Error message
Invalid Request
What it means
After reading the full HTTP header, the bridge splits the request line on spaces expecting exactly 3 parts (method, address, protocol) via bytes.SplitN(b, " ", 3). If the split does not yield 3 elements, the request line is malformed and the request is rejected as invalid. This is a sanity check before method/address extraction.
Source
Thrown at socks5tohttp.go:114
b := make([]byte, 0, 1024)
for {
var b1 [1024]byte
n, err := c.Read(b1[:])
if err != nil {
return err
}
b = append(b, b1[:n]...)
if bytes.Contains(b, []byte{0x0d, 0x0a, 0x0d, 0x0a}) {
break
}
if len(b) >= 2083+18 {
return errors.New("HTTP header too long")
}
}
bb := bytes.SplitN(b, []byte(" "), 3)
if len(bb) != 3 {
return errors.New("Invalid Request")
}
method, address := string(bb[0]), string(bb[1])
var addr string
if method == "CONNECT" {
addr = address
}
if method != "CONNECT" {
var err error
addr, err = GetAddressFromURL(address)
if err != nil {
return err
}
}
tmp, err := s.Dial.Dial("tcp", addr)
if err != nil {
return err
}View on GitHub (pinned to 5cd13ef3b1)
Solutions
- Ensure the client sends an HTTP/1.1 request with a full 3-token request line (method SP absolute-URI SP HTTP/1.x)
- Do not send TLS or HTTP/2 traffic through this bridge - it only parses HTTP/1.x plaintext
- For CONNECT, send 'CONNECT host:port HTTP/1.1' exactly
- Capture a hex dump of the first bytes the client sends to confirm the wire format
Example fix
// before: HTTP/2 preface confuses the parser
client := &http2.Transport{}
// after: force HTTP/1.1 with absolute-form URI
client := &http.Transport{}
req, _ := http.NewRequest("GET", "http://target.example/path", nil) Defensive patterns
Strategy: validation
Validate before calling
func isWellFormedRequestLine(line string) bool {
parts := strings.SplitN(line, " ", 3)
return len(parts) == 3 &&
parts[0] != "" && parts[1] != "" &&
strings.HasPrefix(parts[2], "HTTP/1.")
} Prevention
- Force clients to HTTP/1.1 (disable HTTP/2 and TLS for this hop)
- Use absolute-form URIs through proxies
- Sanity-check the first bytes of the stream before parsing
- Use CONNECT host:port HTTP/1.1 for tunneling
When it happens
Trigger: Handle() receives data whose first line is not a well-formed HTTP request line like 'GET http://host/path HTTP/1.1' - e.g. a TLS ClientHello, raw SOCKS data, HTTP/2 preface 'PRI * HTTP/2.0', or an empty/garbage stream.
Common situations: Pointing a plain-HTTP-only bridge at an HTTPS (TLS) client; an HTTP/2 client connecting without downgrade; a client sending a request line with a missing target or protocol token; binary garbage on the port.
Related errors
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/ac39bff7c8a23323.
Report an issue: GitHub.