accepts

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package accepts performs HTTP content negotiation based on the Accept, Accept-Language, Accept-Charset and Accept-Encoding request headers. It is a port of the npm accepts package (the higher-level wrapper around negotiator that Express uses for req.accepts, req.acceptsLanguages, req.acceptsCharsets and req.acceptsEncodings) built with only the Go standard library.

You reach for this package on the server side whenever a single endpoint can respond in more than one representation and you want the client's stated preferences to pick which one to send. Typical uses are choosing between JSON and HTML for the same resource, selecting a UI language, agreeing on a character set, or deciding whether to compress a response with gzip. Rather than parsing the raw header strings yourself, you hand the request headers to New and then ask, for each dimension, which of the representations you are able to produce ("offers") the client prefers.

Internally each Accept* header is split on commas into individual entries, each entry is split on semicolons to separate the value from its parameters, and any q= (case-insensitive) parameter is parsed as a floating-point quality weight that defaults to 1.0 when absent or malformed. Media types are further split into type/subtype, language tags into primary/sublanguage, and charsets and encodings are treated as opaque tokens. Each offer you pass in is matched against every parsed spec and scored by two axes: the quality value and a specificity score (an exact type/subtype or primary-sub language match beats a type/* or bare-primary match, which in turn beats a */* or * wildcard). The results are then ordered by descending quality, then descending specificity, then the original offer order, using a stable sort so ties preserve caller order.

Several edge cases are handled to mirror real content negotiation. An offer whose effective quality is zero (for example a spec written as application/json;q=0) is treated as unacceptable and dropped, so the singular Type, Language, Charset and Encoding helpers return the empty string for it. When no offers are supplied the plural methods return the acceptable header values themselves in preference order. When the relevant header is absent the package follows HTTP's "absence means anything is acceptable" rule and returns the offers unchanged. Encoding is special: the identity (no-transform) encoding is always considered acceptable unless it is explicitly disabled with identity;q=0, and a *;q=0 wildcard can be used to forbid every encoding that was not named. Media-type offers may be given either as full MIME types ("application/json") or as short extension-style names ("json", "html", "png"), which are expanded through a small built-in shorthand table.

Compared with the Node original the public surface is intentionally close: the plural methods correspond to accepts.types/languages/charsets/encodings and the singular ones to their first-result convenience forms. The main deliberate differences are idiomatic Go ones. Offers are passed as variadic string arguments instead of an array, results come back as native []string and string values, and the shorthand-to-MIME expansion is a fixed internal map rather than the mime module's full extension database, so exotic extensions fall back to application/<name>. The negotiation weighting, tie-breaking and wildcard semantics are otherwise designed to match the behavior Express developers expect from the npm package.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Accepts

type Accepts struct {
	// contains filtered or unexported fields
}

Accepts negotiates acceptable response representations for a request based on its Accept* headers.

func New

func New(header http.Header) *Accepts

New creates an Accepts from the given request headers, reading the Accept, Accept-Language, Accept-Charset and Accept-Encoding fields.

func (*Accepts) Charset

func (a *Accepts) Charset(offers ...string) string

Charset returns the single best charset from offers, or "".

func (*Accepts) Charsets

func (a *Accepts) Charsets(offers ...string) []string

Charsets returns the acceptable charsets from offers in preference order, or all header charsets when no offers are given.

func (*Accepts) Encoding

func (a *Accepts) Encoding(offers ...string) string

Encoding returns the single best encoding from offers, or "".

Example

ExampleAccepts_Encoding chooses a response compression scheme. The Accept-Encoding header lists the encodings a client understands, and Encoding returns the best offered match. The identity (uncompressed) encoding is always implicitly acceptable unless explicitly disabled, but here gzip is preferred over the lower-weighted deflate. This is the negotiation Express performs before compressing a response.

package main

import (
	"fmt"
	"net/http"

	"github.com/malcolmston/express/accepts"
)

func main() {
	h := http.Header{}
	h.Set("Accept-Encoding", "gzip, deflate;q=0.5")

	a := accepts.New(h)
	fmt.Println(a.Encoding("gzip", "deflate"))
}
Output:
gzip

func (*Accepts) Encodings

func (a *Accepts) Encodings(offers ...string) []string

Encodings returns the acceptable encodings from offers in preference order, or all header encodings when no offers are given. The "identity" encoding is always considered acceptable unless it is explicitly disallowed (q=0).

func (*Accepts) Language

func (a *Accepts) Language(offers ...string) string

Language returns the single best language from offers, or "".

Example

ExampleAccepts_Language negotiates a UI language from the Accept-Language header. Each language tag may carry a quality weight, and Language returns the offered tag with the highest weight. Here "en" outranks "fr" because it was given q=0.9 versus q=0.8, so the English offer is chosen. Absent or malformed weights default to 1.0, matching HTTP content negotiation.

package main

import (
	"fmt"
	"net/http"

	"github.com/malcolmston/express/accepts"
)

func main() {
	h := http.Header{}
	h.Set("Accept-Language", "en-US, en;q=0.9, fr;q=0.8")

	a := accepts.New(h)
	fmt.Println(a.Language("fr", "en"))
}
Output:
en

func (*Accepts) Languages

func (a *Accepts) Languages(offers ...string) []string

Languages returns the acceptable languages from offers in preference order, or all header languages when no offers are given.

func (*Accepts) Type

func (a *Accepts) Type(offers ...string) string

Type returns the single best media type from offers, or "" if none are acceptable.

Example

ExampleAccepts_Type shows server-side content negotiation for a response body. A request carries an Accept header listing the media types the client will take, each with an optional quality weight. New wraps the request headers and Type picks the single best match from the representations the server can actually produce. Here the client slightly prefers HTML over JSON, so Type returns "html" even though "json" was offered first.

package main

import (
	"fmt"
	"net/http"

	"github.com/malcolmston/express/accepts"
)

func main() {
	h := http.Header{}
	h.Set("Accept", "text/html, application/json;q=0.9")

	a := accepts.New(h)
	fmt.Println(a.Type("json", "html"))
}
Output:
html

func (*Accepts) Types

func (a *Accepts) Types(offers ...string) []string

Types returns the subset of offers that are acceptable per the Accept header, ordered by preference. With no offers it returns all acceptable media types from the header in preference order.

Example

ExampleAccepts_Types returns every acceptable offer in preference order rather than just the top one. The offers may be short extension-style names such as "json" and "html", which are expanded to full MIME types internally. Results are ordered by descending quality and then by specificity, with ties falling back to the order the offers were passed. This is useful when the caller wants to try representations in turn rather than commit to one.

package main

import (
	"fmt"
	"net/http"

	"github.com/malcolmston/express/accepts"
)

func main() {
	h := http.Header{}
	h.Set("Accept", "text/html, application/json;q=0.9")

	a := accepts.New(h)
	fmt.Println(a.Types("json", "html"))
}
Output:
[html json]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL