From 2582515b4deb4124d5b128aedd81120e2e06d334 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Mon, 20 Dec 2021 11:08:54 +0100 Subject: [PATCH] return first offer when no accept header set (#351) --- internal/api/negotiate.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/api/negotiate.go b/internal/api/negotiate.go index 4d529b3d..5f772daa 100644 --- a/internal/api/negotiate.go +++ b/internal/api/negotiate.go @@ -56,17 +56,18 @@ var HTMLAcceptHeaders = []Offer{ // slice of Offers, and performs content negotiation for the given request // with the given content-type offers. It will return a string representation // of the first suitable content-type, or an error if something goes wrong or -// a suiteable content-type cannot be matched. +// a suitable content-type cannot be matched. // // For example, if the request in the *gin.Context has Accept headers of value // [application/json, text/html], and the provided offers are of value // [application/json, application/xml], then the returned string will be // 'application/json', which indicates the content-type that should be returned. // -// If there are no Accept headers in the request, or the length of offers is 0, -// then an error will be returned, so this function should only be called in places -// where format negotiation is actually needed and headers are expected to be present -// on incoming requests. +// If the length of offers is 0, then an error will be returned, so this function +// should only be called in places where format negotiation is actually needed. +// +// If there are no Accept headers in the request, then the first offer will be returned, +// under the assumption that it's better to serve *something* than error out completely. // // Callers can use the offer slices exported in this package as shortcuts for // often-used Accept types. @@ -77,16 +78,17 @@ func NegotiateAccept(c *gin.Context, offers ...Offer) (string, error) { return "", errors.New("no format offered") } - accepts := c.Request.Header.Values("Accept") - if len(accepts) == 0 { - return "", fmt.Errorf("no Accept header(s) set on incoming request; this endpoint offers %s", offers) - } - strings := []string{} for _, o := range offers { strings = append(strings, string(o)) } + accepts := c.Request.Header.Values("Accept") + if len(accepts) == 0 { + // there's no accept header set, just return the first offer + return strings[0], nil + } + format := c.NegotiateFormat(strings...) if format == "" { return "", fmt.Errorf("no format can be offered for requested Accept header(s) %s; this endpoint offers %s", accepts, offers)