{"record":{"id":"a42312ec1ad84400","repo":"geektutu/7days-golang","slug":"unexpected-http-response-a42312","errorCode":null,"errorMessage":"unexpected HTTP response: ","messagePattern":"unexpected HTTP response: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day7-registry/client.go","lineNumber":295,"sourceCode":"}\n\n// Dial connects to an RPC server at the specified network address\nfunc Dial(network, address string, opts ...*Option) (*Client, error) {\n\treturn dialTimeout(NewClient, network, address, opts...)\n}\n\n// NewHTTPClient new a Client instance via HTTP as transport protocol\nfunc NewHTTPClient(conn net.Conn, opt *Option) (*Client, error) {\n\t_, _ = io.WriteString(conn, fmt.Sprintf(\"CONNECT %s HTTP/1.0\\n\\n\", defaultRPCPath))\n\n\t// Require successful HTTP response\n\t// before switching to RPC protocol.\n\tresp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: \"CONNECT\"})\n\tif err == nil && resp.Status == connected {\n\t\treturn NewClient(conn, opt)\n\t}\n\tif err == nil {\n\t\terr = errors.New(\"unexpected HTTP response: \" + resp.Status)\n\t}\n\treturn nil, err\n}\n\n// DialHTTP connects to an HTTP RPC server at the specified network address\n// listening on the default HTTP RPC path.\nfunc DialHTTP(network, address string, opts ...*Option) (*Client, error) {\n\treturn dialTimeout(NewHTTPClient, network, address, opts...)\n}\n\n// XDial calls different functions to connect to a RPC server\n// according the first parameter rpcAddr.\n// rpcAddr is a general format (protocol@addr) to represent a rpc server\n// eg, http@10.0.0.1:7001, tcp@10.0.0.1:9999, unix@/tmp/geerpc.sock\nfunc XDial(rpcAddr string, opts ...*Option) (*Client, error) {\n\tparts := strings.Split(rpcAddr, \"@\")\n\tif len(parts) != 2 {\n\t\treturn nil, fmt.Errorf(\"rpc client err: wrong format '%s', expect protocol@addr\", rpcAddr)","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day7-registry/client.go#L277-L313","documentation":"NewHTTPClient dials an RPC server over HTTP CONNECT. After sending CONNECT it reads the server's HTTP response; if the response is not the expected 'Connected to Gee RPC' status, the library wraps the raw status line into this error. It means the handshake to switch from HTTP to the RPC protocol failed.","triggerScenarios":"Calling NewHTTPClient (via XDialHTTP or DialHTTP) against an address that is not a GeeRPC HTTP server, a server returning a non-101/200 CONNECT response, a plain HTTP endpoint that replies with e.g. '404 Not Found' or '400 Bad Request' to CONNECT, or a proxy/gateway intercepting the CONNECT request.","commonSituations":"Pointing the client at the wrong port or at a regular REST/web server; firewalls or reverse proxies rejecting CONNECT; connecting to a GeeRPC server started without the HTTP mode; version mismatch where the server's connected status string differs.","solutions":["Verify the server address points to a GeeRPC server started via http.ListenAndServe (StartHTTP mode), not a normal TCP RPC port or unrelated web server","Check the full error string: resp.Status tells you what the server actually returned (e.g. 404) and fix routing/port accordingly","Remove or reconfigure proxies/load balancers between client and server that do not forward CONNECT","Confirm client and server use the same gee-rpc version so the magic 'connected' status string matches"],"exampleFix":"// before\nclient, err := geerpc.XDialHTTP(\"tcp\", \"localhost:9999\", geerpc.GeeOption{...}) // 9999 is a plain web server\n// after\nclient, err := geerpc.XDialHTTP(\"tcp\", \"localhost:7000\", geerpc.GeeOption{...}) // 7000 runs gee-rpc in HTTP mode","handlingStrategy":"try-catch","validationCode":"// Go has no pre-call hook into the handshake; verify the endpoint before dialing\nfunc isGeeRPC Compatible(addr string) bool {\n    conn, err := net.DialTimeout(\"tcp\", addr, 2*time.Second)\n    if err != nil { return false }\n    conn.Close()\n    return true\n}\n// additionally confirm the target is your gee-rpc HTTP server port, not a web server","typeGuard":null,"tryCatchPattern":"client, err := geerpc.NewHTTPClient(conn)\nif err != nil {\n    if strings.Contains(err.Error(), \"unexpected HTTP response\") {\n        log.Fatalf(\"endpoint %s is not a gee-rpc HTTP server: %v\", addr, err)\n    }\n    return err\n}","preventionTips":["Run gee-rpc servers in HTTP mode on dedicated, documented ports","Keep client and server gee-rpc versions in sync","Avoid proxies that mangle CONNECT between client and server","Alert on this error at startup rather than failing silently"],"tags":["go","rpc","http","network"],"backgroundTag":"http-connect-handshake-failed","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}