Negotiation
Content Negotiation
MIME types
Commonly used data formats:
const (
MIMEApplicationJSON = "application/json"
MIMEApplicationJSONCharsetUTF8 = "application/json; charset=UTF-8"
MIMEApplicationJavaScript = "application/javascript"
MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=UTF-8"
MIMEApplicationXML = "application/xml"
MIMEApplicationXMLCharsetUTF8 = "application/xml; charset=UTF-8"
MIMETextXML = "text/xml"
MIMETextXMLCharsetUTF8 = "text/xml; charset=UTF-8"
MIMEApplicationForm = "application/x-www-form-urlencoded"
MIMEApplicationProtobuf = "application/protobuf"
MIMEApplicationMsgpack = "application/msgpack"
MIMETextHTML = "text/html"
MIMETextHTMLCharsetUTF8 = "text/html; charset=UTF-8"
MIMETextPlain = "text/plain"
MIMETextPlainCharsetUTF8 = "text/plain; charset=UTF-8"
MIMEMultipartForm = "multipart/form-data"
MIMEOctetStream = "application/octet-stream"
)
Headers
Some commonly used header names:
const (
HeaderAccept = "Accept"
HeaderAcceptCharset = "Accept-Charset"
HeaderAcceptEncoding = "Accept-Encoding"
HeaderAcceptLanguage = "Accept-Language"
// HeaderAllow is the name of the "Allow" header field used to list the set of methods
// advertised as supported by the target resource. Returning an Allow header is mandatory
// for status 405 (method not found) and useful for the OPTIONS method in responses.
// See RFC 7231: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
HeaderAllow = "Allow"
HeaderAuthorization = "Authorization"
HeaderContentDisposition = "Content-Disposition"
HeaderContentEncoding = "Content-Encoding"
HeaderContentLength = "Content-Length"
HeaderContentType = "Content-Type"
HeaderCookie = "Cookie"
HeaderSetCookie = "Set-Cookie"
HeaderIfModifiedSince = "If-Modified-Since"
HeaderLastModified = "Last-Modified"
HeaderLocation = "Location"
HeaderUpgrade = "Upgrade"
HeaderVary = "Vary"
HeaderWWWAuthenticate = "WWW-Authenticate"
HeaderXForwardedFor = "X-Forwarded-For"
HeaderXForwardedProto = "X-Forwarded-Proto"
HeaderXForwardedProtocol = "X-Forwarded-Protocol"
HeaderXForwardedSsl = "X-Forwarded-Ssl"
HeaderXUrlScheme = "X-Url-Scheme"
HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
HeaderXRealIP = "X-Real-IP"
HeaderXRequestID = "X-Request-ID"
HeaderXRequestedWith = "X-Requested-With"
HeaderServer = "Server"
HeaderOrigin = "Origin"
HeaderCacheControl = "Cache-Control"
HeaderConnection = "Connection"
// Access control
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers"
HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin"
HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods"
HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers"
HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"
HeaderAccessControlMaxAge = "Access-Control-Max-Age"
// Security
HeaderStrictTransportSecurity = "Strict-Transport-Security"
HeaderXContentTypeOptions = "X-Content-Type-Config"
HeaderXXSSProtection = "X-XSS-Protection"
HeaderXFrameOptions = "X-Frame-Config"
HeaderContentSecurityPolicy = "Content-Security-Policy"
HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
HeaderXCSRFToken = "X-CSRF-Token"
HeaderReferrerPolicy = "Referrer-Policy"
)
type Negotiator
Content negotiation struct
type Negotiator struct {
// Cache capacity, we reuse parsing results when negotiation headers are the same.
capacity int
// Sometimes the parsed Accept values are not the standard
// values defined by W3C. We rewrite them into standard format through this function.
onParse func(*Accept)
}
An HTTP request content negotiation tool that handles negotiation based on the following headers:
- Accept, content types the client can handle, expressed as MIME types;
- Accept-Charset, charset types the client can handle, such as
utf-8oriso-8859-1; - Accept-Encoding, content encoding methods the client can understand, typically compression algorithms;
- Accept-Language, natural languages the client can understand, such as
zh.
func NewNegotiator
func NewNegotiator(capacity int, onParse func(*Accept)) *Negotiator
Creates a content negotiation tool.
func (*Negotiator) Slice
func (n *Negotiator) Slice(header string) AcceptSlice
Parses HTTP Accept(-Charset|-Encoding|-Language) headers and returns an AcceptSlice instance. The result is sorted in descending order according to the type and weight factor. If the type and weight are the same, they are sorted by order of appearance.
We can refer to the standard: https://www.rfc-editor.org/rfc/rfc9110.html#name-accept
func (*Negotiator) Charset
func (n *Negotiator) Charset(r *http.Request, charsets ...string) string
Parses the Accept-Charset header and returns the charset with the highest weight from the provided charset list charsets. Returns an empty string if there's no match.
func (*Negotiator) Encoding
func (n *Negotiator) Encoding(r *http.Request, encodings ...string) string
Parses the Accept-Encoding header and returns the encoding with the highest weight from the provided encoding list encodings. Returns an empty string if there's no match.
func (*Negotiator) Language
func (n *Negotiator) Language(r *http.Request, languages ...string) string
Parses the Accept-Language header and returns the language with the highest weight from the provided language list languages. Returns an empty string if there's no match.
func (*Negotiator) Type
func (n *Negotiator) Type(r *http.Request, types ...string) string
Parses the Accept header and returns the content type with the highest weight from the provided content type list types. Returns an empty string if there's no match.
The types parameter values can be standard media types (like application/json) or extensions (like json, xml, etc.).
func (*Negotiator) Accepts
func (n *Negotiator) Accepts(header string, ctypes ...string) string
Parses header header and returns the content type with the highest weight from the provided parameter list ctypes. Returns an empty string if there's no match.
This method is a combined version of the above 4 methods, but differs slightly from Negotiator#Type in that it doesn't support judging content types by extension.
type Accept
type Accept struct {
Type string
Subtype string
Quality float64
Extensions map[string]any
}
Represents a parsed unit value of Accept(-Charset|-Encoding|-Language) headers.
type AcceptSlice
type AcceptSlice []Accept
Represents parsed values of Accept(-Charset|-Encoding|-Language) headers, which is a slice of Accept structs.
func (AcceptSlice) Len()
func (as AcceptSlice) Len() int
Implements the Len() method of the sort.Interface interface.
func (AcceptSlice) Less
func (as AcceptSlice) Less(i, j int) bool
Implements the Less() method of the sort.Interface interface, sorting elements in descending order of priority.
func (AcceptSlice) Swap
func (as AcceptSlice) Swap(i, j int)
Implements the Swap() method of the sort.Interface interface.
func (AcceptSlice) Negotiate
func (as AcceptSlice) Negotiate(ctypes ...string) (string, int, error)
Returns a type from the slice that can be accepted by the client. Returns an empty string if no type is found.
func (AcceptSlice) Accepts
func (as AcceptSlice) Accepts(ctype string) bool
Returns true if the provided type ctype can be accepted by the client, otherwise returns false.