Skip to content
/ sling Public

Conversation

@Navyum
Copy link

@Navyum Navyum commented Jun 18, 2025

fix: improve Host header handling in addHeaders function

Summary

This PR adds support for explicitly setting the HTTP Host header via the sling API. It ensures that when a user sets the "Host" header using .Set("Host", ...), the generated *http.Request will have its Host field set accordingly, allowing for correct routing in scenarios such as reverse proxies, load balancers, or virtual hosting.

Changes

Updated the addHeaders() method to check for a "Host" header in the request headers.
If the "Host" header is present, its value is assigned to the req.Host field of the generated *http.Request.
This ensures that the actual HTTP Host header sent over the wire matches the intended value, not just the header map.

Why?

Go’s net/http library uses the req.Host field to set the Host header in outgoing requests. Simply setting the "Host" header in the header map does not affect the actual Host header sent by the HTTP client.
Many real-world scenarios (such as AWS ELB routing, Kubernetes Ingress, or multi-tenant APIs) require the ability to set a custom Host header. Without this change, users cannot achieve this behavior using sling’s fluent API, and must manually modify the generated request, which breaks the chainable design and developer experience.

Currently, developers who need to set a custom Host header with sling must use a workaround: after building the request with sling.Request(), they must manually assign the desired value to the req.Host field before sending the request with an HTTP client, like so:

req, err := sling.New().
    Post("https://example.com/api").
    Request()
if err != nil {
    // handle error
}
req.Host = "custom-host"
resp, err := http.DefaultClient.Do(req)

This approach is not elegant because it breaks the fluent, chainable API design that sling promotes. It also requires users to be aware of Go’s internal HTTP mechanics, which can be confusing and error-prone. By supporting Host assignment directly in the sling API, we improve developer experience and make the intent explicit and idiomatic.

Example usage:

resp, err := sling.New().
    Post("https://example.com/api").
    Set("Host", "custom-host").
    Body(jsonBody).
    Request()
if err != nil {
    // handle error
}
// req.Host will now be set to "custom-host"

@Navyum
Copy link
Author

Navyum commented Jun 18, 2025

golang net/http official description as follow:

For client requests, Host optionally overrides the Host header to send. If empty, the Request.Write method uses the value of URL.Host.
https://pkg.go.dev/net/http#Request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant