Headers
ctx.Request.Headers provides access to HTTP headers sent by the client during the current request.
The headers contain additional information about the request, such as the type of content, user agent, accepted languages or any custom header sent by the client.
This object only allows to consult the headers received from the client. To manage the headers that will be sent to the client uses Response Headers.
func GET(ctx *gox.Context) gox.Page {
userAgent, ok := ctx.Request.Headers.Get("User-Agent")
if !ok {
return <p>Unknown client</p>
}
return <p>{{ userAgent }}</p>
} Structure
ctx.Request.Headers implement the following API:
Headers
{
Get(key string) (string, bool)
GetAll(key string) ([]string, bool)
Has(key string) bool
IsEmpty() bool
Count() int
Keys() []string
Values() []string
Entries() map[string][]string
} All methods are read only.
Header searches do not distinguish between capital letters and lower letters.
Methods
| Method | Description |
|---|---|
| Get() | Returns the first value associated with a header. |
| GetAll() | Returns all values associated with a header. |
| Has() | It indicates if a header exists. |
| IsEmpty() | It indicates whether the collection contains headers. |
| Count() | Returns the number of headers available. |
| Keys() | Returns all the keys to the collection. |
| Values() | Returns the first value associated with each header. |
| Entries() | Returns all headers along with all associated values. |
Get()
Firma:func (Headers) Get(key string) (string, bool)
Get() returns the first value associated with a header and indicates whether the header exists.
func GET(ctx *gox.Context) gox.Page {
userAgent, ok := ctx.Request.Headers.Get("User-Agent")
// ok == true
// userAgent == "Mozilla/5.0..."
return <p>{{ userAgent }}</p>
} When the header does not exist, it returns an empty string and false.
func GET(ctx *gox.Context) gox.Page {
traceID, ok := ctx.Request.Headers.Get("X-Trace-ID")
if !ok {
return <p>Trace ID not found</p>
}
return <p>{{ traceID }}</p>
} When a header contains several values, Get() return only the first one.
Use Get() when you only need the first value associated with a header.
GetAll()
Firma:func (Headers) GetAll(key string) ([]string, bool)
GetAll() returns all the values associated with a header and indicates whether the header exists.
func GET(ctx *gox.Context) gox.Page {
accept, ok := ctx.Request.Headers.GetAll("Accept")
if !ok {
return <p>Accept header not found</p>
}
return <ul>
<:for value range={{ accept }}>
<li>{{ value }}</li>
</:for>
</ul>
} When the header does not exist or contains values, it returns nil and false.
func GET(ctx *gox.Context) gox.Page {
languages, ok := ctx.Request.Headers.GetAll("Accept-Language")
// languages == nil
// ok == false
if !ok {
return <p>No preferred languages</p>
}
return <ul>
<:for language range={{ languages }}>
<li>{{ language }}</li>
</:for>
</ul>
} The returned slice is a separate copy. Modifying it does not change the original headers of the request.
func GET(ctx *gox.Context) gox.Page {
values, ok := ctx.Request.Headers.GetAll("Accept")
if !ok {
return <p>Accept header not found</p>
}
values[0] = "modified"
original, _ := ctx.Request.Headers.Get("Accept")
// original conserva el valor recibido del cliente
return <p>{{ original }}</p>
} Use this method when a header can have several values within the same request.
Has()
Firma:func (Headers) Has(key string) bool
Has() indicates whether a header exists and contains at least one value.
func GET(ctx *gox.Context) gox.Page {
if ctx.Request.Headers.Has("Authorization") {
return <p>Authorized request</p>
}
return <p>Anonymous request</p>
} Has() It only checks the existence of the header. It does not value or interpret its content.
Use Has() when you only need to check the existence of a header.
When you also need to see its value, use it directly Get() to avoid looking for the same header twice.
func GET(ctx *gox.Context) gox.Page {
authorization, ok := ctx.Request.Headers.Get("Authorization")
if !ok {
return <p>Anonymous request</p>
}
return <p>{{ authorization }}</p>
} IsEmpty()
Firma:func (Headers) IsEmpty() bool
IsEmpty() indicates whether the collection does not contain headers with values.
func GET(ctx *gox.Context) gox.Page {
if ctx.Request.Headers.IsEmpty() {
return <p>No headers</p>
}
return <p>Headers available</p>
} Under normal conditions, an HTTP request usually contains several headers.
Count()
Firma:func (Headers) Count() int
Count() returns the number of headers available.
func GET(ctx *gox.Context) gox.Page {
total := ctx.Request.Headers.Count()
return <p>{{ total }}</p>
} Each header name counts as a single element, although it has several associated values.
For example, a header with three values continues to count as a single header.
Keys()
Firma:func (Headers) Keys() []string
Keys() returns all the keys present in the collection.
func GET(ctx *gox.Context) gox.Page {
keys := ctx.Request.Headers.Keys()
return <ul>
<:for key range={{ keys }}>
<li>{{ key }}</li>
</:for>
</ul>
} Each header name appears only once, even if it has several associated values.
The returned slice is a separate copy and can be modified without altering the request headers.
Values()
Firma:func (Headers) Values() []string
Values() returns the first value associated with each header.
func GET(ctx *gox.Context) gox.Page {
values := ctx.Request.Headers.Values()
return <ul>
<:for value range={{ values }}>
<li>{{ value }}</li>
</:for>
</ul>
} When a header contains several values, only the first one is included.
Values() only returns the values and does not retain the relationship to the name of each header.
If you need to keep all the values associated with each header, use Entries().
The returned slice is a separate copy and can be modified without altering the request.
Entries()
Firma:func (Headers) Entries() map[string][]string
Entries() returns all headers along with all their values.
func GET(ctx *gox.Context) gox.Page {
headers := ctx.Request.Headers.Entries()
// headers["Accept"]
// headers["User-Agent"]
// headers["Authorization"]
return <p>{{ len(headers) }}</p>
} Each map key represents the name of a header and contains all associated values.
func GET(ctx *gox.Context) gox.Page {
headers := ctx.Request.Headers.Entries()
return <ul>
<:for key, values range={{ headers }}>
<li>
<strong>{{ key }}</strong>
<ul>
<:for value range={{ values }}>
<li>{{ value }}</li>
</:for>
</ul>
</li>
</:for>
</ul>
} Both the map and its slices are independent copies. Modifying them does not change the original headers of the request.
func GET(ctx *gox.Context) gox.Page {
headers := ctx.Request.Headers.Entries()
headers["Accept"][0] = "modified"
headers["X-Custom"] = []string{"example"}
accept, _ := ctx.Request.Headers.Get("Accept")
hasCustom := ctx.Request.Headers.Has("X-Custom")
// accept conserva el valor recibido del cliente
// hasCustom == false
return <p>{{ accept }}</p>
} Use Entries() when you need to go through the complete collection by preserving the relationship between each header and its values.
Headers with empty values
The signature of Get() allows to distinguish between an absent header and a present header whose value is an empty string.
A header with no content:
X-Custom: produce:
func GET(ctx *gox.Context) gox.Page {
value, ok := ctx.Request.Headers.Get("X-Custom")
// value == ""
// ok == true
return <p>{{ value }}</p>
} When the header was not sent:
func GET(ctx *gox.Context) gox.Page {
value, ok := ctx.Request.Headers.Get("X-Custom")
// value == ""
// ok == false
return <p>{{ value }}</p>
} This difference makes it possible to determine whether the client omitted the header or sent it explicitly with an empty value.
Full example
The following example shows several common operations on the headers of an request:
func GET(ctx *gox.Context) gox.Page {
headers := ctx.Request.Headers
userAgent, hasUserAgent := headers.Get("User-Agent")
accept, hasAccept := headers.GetAll("Accept")
keys := headers.Keys()
if !hasUserAgent {
userAgent = "Unknown client"
}
return <main>
<p>User-Agent: {{ userAgent }}</p>
<p>Total headers: {{ headers.Count() }}</p>
<p>Authorization: {{ headers.Has("Authorization") }}</p>
<h2>Accept</h2>
<:if !hasAccept>
<p>Accept header not found</p>
<:else>
<ul>
<:for value range={{ accept }}>
<li>{{ value }}</li>
</:for>
</ul>
</:if>
<h2>Header names</h2>
<ul>
<:for key range={{ keys }}>
<li>{{ key }}</li>
</:for>
</ul>
</main>
} Best practices
- Use
Get()when you only need the first value of a header. - Check the boolean value returned by
Get()when the header may not exist. - Use
GetAll()for headers that may contain several values. - Check the boolean value returned by
GetAll()before using the slice. - Use
Has()when you only need to check the existence of a header. - When you also need the value, use it directly
Get()to avoid consulting the collection twice. - Use
Values()when you only need to go through the first value of each header. - Use
Entries()when you need to keep the relationship between each header and all its values. - It avoids assuming that all headers contain a single value.
- It avoids relying on the capitalization used by the client when sending the name of a header.
- Do not use headers received from the client as reliable values without previously validating them.
- Valid especially headers related to authentication, proxies, IP addresses and readdresses.
To learn more about RequestSee your documentation. To learn more about CookiesSee your documentation. To learn more about QuerySee your documentation. To learn more about FormSee your documentation. To learn more about Context, check your documentation.