geektutu/7days-golang · error
unexpected HTTP response:
Error message
unexpected HTTP response:
What it means
NewHTTPClient performs the xRPC CONNECT handshake: it sends an HTTP CONNECT request and waits for a response whose status equals the magic "connected" string before switching to the RPC protocol. If the response is HTTP but not the expected status, it wraps the status in "unexpected HTTP response: ". This indicates the server did not recognize the HTTP RPC handshake.
Source
Thrown at gee-rpc/day6-load-balance/client.go:295
}
// Dial connects to an RPC server at the specified network address
func Dial(network, address string, opts ...*Option) (*Client, error) {
return dialTimeout(NewClient, network, address, opts...)
}
// NewHTTPClient new a Client instance via HTTP as transport protocol
func NewHTTPClient(conn net.Conn, opt *Option) (*Client, error) {
_, _ = io.WriteString(conn, fmt.Sprintf("CONNECT %s HTTP/1.0\n\n", defaultRPCPath))
// Require successful HTTP response
// before switching to RPC protocol.
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
if err == nil && resp.Status == connected {
return NewClient(conn, opt)
}
if err == nil {
err = errors.New("unexpected HTTP response: " + resp.Status)
}
return nil, err
}
// DialHTTP connects to an HTTP RPC server at the specified network address
// listening on the default HTTP RPC path.
func DialHTTP(network, address string, opts ...*Option) (*Client, error) {
return dialTimeout(NewHTTPClient, network, address, opts...)
}
// XDial calls different functions to connect to a RPC server
// according the first parameter rpcAddr.
// rpcAddr is a general format (protocol@addr) to represent a rpc server
// eg, http@10.0.0.1:7001, tcp@10.0.0.1:9999, unix@/tmp/geerpc.sock
func XDial(rpcAddr string, opts ...*Option) (*Client, error) {
parts := strings.Split(rpcAddr, "@")
if len(parts) != 2 {
return nil, fmt.Errorf("rpc client err: wrong format '%s', expect protocol@addr", rpcAddr)View on GitHub (pinned to cf36443821)
Solutions
- Register the HTTP handshake on the server (HandleHTTP) and serve DefaultHTTPRPCPath via http.ListenAndServe
- Verify the address/port points to the xRPC HTTP endpoint, not a plain web server or the raw-RPC port
- Use Dial (raw TCP) instead of DialHTTP if the server is not an HTTP-handshake server
- Check proxies/load balancers that may intercept or rewrite the CONNECT request
Example fix
// before
client, err := geeprc.DialHTTP("tcp", "localhost:9999") // plain TCP rpc server
// after
// server side:
geeprc.HandleHTTP()
http.ListenAndServe("localhost:9999", nil)
// then client:
client, err := geeprc.DialHTTP("tcp", "localhost:9999") Defensive patterns
Strategy: validation
Validate before calling
// verify the server speaks the xRPC HTTP handshake before dialing
conn, _ := net.DialTimeout("tcp", addr, 3*time.Second)
req, _ := http.NewRequest("CONNECT", "http://"+addr+DefaultHTTPRPCPath, nil)
req.Write(conn)
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
if err != nil || resp.Status != connected {
return errors.New("endpoint does not support xRPC over HTTP")
} Try / catch
client, err := geeprc.DialHTTP("tcp", addr)
if err != nil {
if strings.HasPrefix(err.Error(), "unexpected HTTP response: ") {
// wrong endpoint/protocol: fall back to raw Dial or fix server registration
}
return err
} Prevention
- Always call geeprc.HandleHTTP() and serve the DefaultHTTPRPCPath on the server
- Keep separate ports for raw xRPC (Dial) and HTTP-handshake xRPC (DialHTTP)
- Verify via curl/CONNECT smoke test before deploying client config
- Check reverse proxies pass the CONNECT request through untouched
When it happens
Trigger: DialHTTP/NewHTTPClient against a port that serves plain HTTP (no xRPC handler on DefaultHTTPRPCPath); server not registered via HandleHTTP; wrong path or proxy intercepting CONNECT; connecting a normal (non-HTTP) xRPC server with DialHTTP.
Common situations: Pointing DialHTTP at an ordinary web server or wrong port; forgetting gee-rpc's HandleHTTP registration on the server; a reverse proxy returning 404/502 for the RPC path; version mismatch where the server expects a different handshake string.
Related errors
- unexpected HTTP response:
- unexpected HTTP response:
- rpc client: call failed:
- number of options is more than 1
- rpc server: service/method request ill-formed:
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/3acc5c553fc0600c.
Report an issue: GitHub.