{"record":{"id":"24714654d56a9a24","repo":"valyala/fasthttp","slug":"invalid-host-q-use-a-host-client-for-multiple-ho","errorCode":null,"errorMessage":"invalid host %q: use a host client for multiple hosts","messagePattern":"invalid host %q: use a host client for multiple hosts","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client.go","lineNumber":550,"sourceCode":"// Response is ignored if resp is nil.\n//\n// The function doesn't follow redirects. Use Get* for following redirects.\n//\n// ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections\n// to the requested host are busy.\n//\n// It is recommended obtaining req and resp via AcquireRequest\n// and AcquireResponse in performance-critical code.\nfunc (c *Client) Do(req *Request, resp *Response) error {\n\turi := req.URI()\n\tif uri == nil {\n\t\treturn ErrorInvalidURI\n\t}\n\n\thost := uri.Host()\n\n\tif bytes.ContainsRune(host, ',') {\n\t\treturn fmt.Errorf(\"invalid host %q: use a host client for multiple hosts\", host)\n\t}\n\n\tisTLS := false\n\tif uri.isHTTPS() {\n\t\tisTLS = true\n\t} else if !uri.isHTTP() {\n\t\treturn fmt.Errorf(\"unsupported protocol %q. http and https are supported\", uri.Scheme())\n\t}\n\n\tc.mOnce.Do(func() {\n\t\tc.m = make(map[string]*HostClient)\n\t\tc.ms = make(map[string]*HostClient)\n\t})\n\thc, err := c.hostClient(host, isTLS)\n\tif err != nil {\n\t\treturn err\n\t}\n","sourceCodeStart":532,"sourceCodeEnd":568,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/client.go#L532-L568","documentation":"The generic fasthttp Client routes requests to per-host HostClients created on demand. A URI whose host contains a comma cannot map to a single host, so Do rejects it and tells you to use a HostClient bound to a specific host instead.","triggerScenarios":"Calling client.Do/DoTimeout/DoDeadline with a request whose RequestURI/URL host contains ',', e.g. \"http://host1,host2/path\" or a comma-joined host list copied from a proxy config or Host header.","commonSituations":"Building a URL by joining multiple backends with commas, reusing a Host header from an inbound request that contained a comma list, load-balancer-style config pasted into the URL.","solutions":["Use fasthttphost-style HostClient with c.Host set explicitly, or fasthttp.HostClient{Addr: ...} per target","Split the comma-joined value and pick/iterate one host per request","Sanitize or reject comma characters when constructing URIs from user input","Fix the code path that interpolates a Host header or config list directly into the URL"],"exampleFix":"// before\nreq.SetRequestURI(\"http://\" + strings.Join(backends, \",\") + \"/api\")\nclient.Do(req, resp)\n// after\nhc := &fasthttp.HostClient{Addr: pickBackend(backends)}\nreq.SetRequestURI(\"http://\" + hc.Addr + \"/api\")\nhc.Do(req, resp)","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(req.URI().String())\nif strings.Contains(u.Host, \",\") { return errors.New(\"multiple hosts in URI; use HostClient\") }","typeGuard":"func isSingleHostURI(uri string) bool {\n    u, err := url.Parse(uri)\n    return err == nil && !strings.Contains(u.Host, \",\")\n}","tryCatchPattern":"err := client.Do(req, resp)\nif err != nil {\n    if strings.Contains(err.Error(), \"use a host client for multiple hosts\") {\n        // fall back to a per-host HostClient\n    }\n}","preventionTips":["Never join multiple backends with commas into one URL","Create one fasthttp.HostClient per upstream host","Sanitize Host headers copied from inbound requests"],"tags":["go","fasthttp","http-client","url-validation"],"backgroundTag":"invalid-request-uri","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}