Documentation ¶
Overview ¶
Package acceptable is a library that handles headers for content negotiation in web applications written in Go. Content negotiation is specified by RFC (http://tools.ietf.org/html/rfc7231) and, less formally, by Ajax (https://en.wikipedia.org/wiki/XMLHttpRequest).
Accept ¶
from https://tools.ietf.org/html/rfc7231#section-5.3.2:
The "Accept" header field can be used by user agents to specify response media types that are acceptable. Accept header fields can be used to indicate that the request is specifically limited to a small set of desired types, as in the case of a request for an in-line image.
A request without any Accept header field implies that the user agent will accept any media type in response.
If the header field is present in a request and none of the available representations for the response have a media type that is listed as acceptable, the origin server can either honor the header field by sending a 406 (Not Acceptable) response, or disregard the header field by treating the response as if it is not subject to content negotiation.
Accept-Language ¶
from https://tools.ietf.org/html/rfc7231#section-5.3.5:
The "Accept-Language" header field can be used by user agents to indicate the set of natural languages that are preferred in the response.
A request without any Accept-Language header field implies that the user agent will accept any language in response.
If the header field is present in a request and none of the available representations for the response have a matching language tag, the origin server can either disregard the header field by treating the response as if it is not subject to content negotiation or honor the header field by sending a 406 (Not Acceptable) response. However, the latter is not encouraged, as doing so can prevent users from accessing content that they might be able to use (with translation software, for example).
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var Debug = func(string, ...interface{}) {}
Debug can be used for observing decisions made by the negotiator. By default it is no-op.
Functions ¶
func RenderBestMatch ¶ added in v0.7.0
func RenderBestMatch(w http.ResponseWriter, req *http.Request, template string, available ...Offer) error
RenderBestMatch uses BestRequestMatch to find the best matching offer for the request, and then renders the response.
Example ¶
package main import ( "net/http" "net/http/httptest" "github.com/rickb777/acceptable" "github.com/rickb777/acceptable/data" "github.com/rickb777/acceptable/processor" "github.com/rickb777/acceptable/templates" ) func main() { // In this example, the same content is available in three languages. Three different // approaches can be used. // 1. simple values can be used en := "Hello!" // get English content // 2. values can be wrapped in a data.Data fr := data.Of("Bonjour!") // get French content // 3. this uses a lazy evaluation function, wrapped in a data.Data es := data.Lazy(func(template string, language string) (interface{}, error) { return "Hola!", nil // get Spanish content - eg from database }) // We're implementing an HTTP handler, so we are given a request and a response. req := &http.Request{} // some incoming request var res http.ResponseWriter = httptest.NewRecorder() // replace with the server's response writer // Now do the content negotiation. This example has six supported content types, all of them // able to serve any of the three example languages. // // The first offer is for JSON - this is often the most widely used because it also supports // Ajax requests. acceptable.RenderBestMatch(res, req, "home.html", acceptable.OfferOf("application/json", "en").Using(processor.JSON(" ")). With("en", en).With("fr", fr).With("es", es), acceptable.OfferOf("application/xml").Using(processor.XML(" ")). With("en", en).With("fr", fr).With("es", es), acceptable.OfferOf("text/csv").Using(processor.CSV()). With("en", en).With("fr", fr).With("es", es), acceptable.OfferOf("text/plain").Using(processor.TXT()). With("en", en).With("fr", fr).With("es", es), templates.TextHtmlOffer("en", "templates/en", ".html", nil). With("en", en).With("fr", fr).With("es", es), templates.ApplicationXhtmlOffer("en", "templates/en", ".html", nil). With("en", en).With("fr", fr).With("es", es), ) // RenderBestMatch returns an error which should be checked }
Output:
Types ¶
type Match ¶ added in v0.3.0
type Match struct { Type string Subtype string Language string Charset string Vary []string Data data.Data Render Processor }
Match holds the best-matched offer after content negotiation and is used for response rendering.
func BestRequestMatch ¶
BestRequestMatch finds the content type and language that best matches the accepted media ranges and languages contained in request headers. The result contains the best match, based on the rules of RFC-7231. On exit, the result will contain the preferred language and charset, if these are known.
Whenever the result is nil, the response should be 406-Not Acceptable.
For all Ajax requests, the available offers are filtered so that only those capable of providing an Ajax response are considered by the content negotiation algorithm. The other offers are discarded.
The order of offers is important. It determines the order they are compared against the request headers, and it determines what defaults will be used when exact matching is not possible.
If no available offers are provided, the response will always be nil. Note too that Ajax requests will result in nil being returned if no offer is capable of handling them, even if other offers are provided.
func (Match) ApplyHeaders ¶ added in v0.3.0
func (m Match) ApplyHeaders(rw http.ResponseWriter) io.Writer
ApplyHeaders sets response headers so that the user agent is notified of the content negotiation decisons made. Four headers may be set, depending on context.
- Content-Type is always set.
- Content-Language is set when a language was selected.
- Content-Encoding is set when the character set is being transcoded
- Vary is set to list the accept headers that led to the three decisions above.
type Offer ¶
type Offer struct { // ContentType is the content type that is to be matched. // Wildcard values may be used. header.ContentType // contains filtered or unexported fields }
Offer holds information about one particular resource representation that can potentially provide an acceptable response.
func OfferOf ¶
OfferOf constructs an Offer easily. Zero or more languages can be specified. If the language is absent, it is assumed to be the wildcard "*". If the content type is blank, it is assumed to be the full wildcard "*/*". Also, contentType can be a partial wildcard "type/*".
func (Offer) Using ¶ added in v0.5.0
Using attaches a processor function to an offer and returns the modified offer. The original offer is unchanged.
Directories ¶
Path | Synopsis |
---|---|
package data provides wrappers for response data, optionally including response headers such as ETag.
|
package data provides wrappers for response data, optionally including response headers such as ETag. |
package header provides parsing rules for content negotiation headers according to RFC-7231.
|
package header provides parsing rules for content negotiation headers according to RFC-7231. |
Package processor contains flexible implementations for rendering JSON, XML, CSV and plain text.
|
Package processor contains flexible implementations for rendering JSON, XML, CSV and plain text. |
Package templates provides tree-based template loading and rendering using HTML templates from the Go standard library.
|
Package templates provides tree-based template loading and rendering using HTML templates from the Go standard library. |