blob: a9b6f27d3d377f9ad5454b91d2d2cb2d90477da2 [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// Copyright 2013 The Go Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd.
6
7// this file was taken from the github.com/golang/gddo repository
8
9package middleware
10
11import (
12 "net/http"
13 "strings"
14
15 "github.com/go-openapi/runtime/middleware/header"
16)
17
18// NegotiateContentEncoding returns the best offered content encoding for the
19// request's Accept-Encoding header. If two offers match with equal weight and
20// then the offer earlier in the list is preferred. If no offers are
21// acceptable, then "" is returned.
22func NegotiateContentEncoding(r *http.Request, offers []string) string {
23 bestOffer := "identity"
24 bestQ := -1.0
25 specs := header.ParseAccept(r.Header, "Accept-Encoding")
26 for _, offer := range offers {
27 for _, spec := range specs {
28 if spec.Q > bestQ &&
29 (spec.Value == "*" || spec.Value == offer) {
30 bestQ = spec.Q
31 bestOffer = offer
32 }
33 }
34 }
35 if bestQ == 0 {
36 bestOffer = ""
37 }
38 return bestOffer
39}
40
41// NegotiateContentType returns the best offered content type for the request's
42// Accept header. If two offers match with equal weight, then the more specific
43// offer is preferred. For example, text/* trumps */*. If two offers match
44// with equal weight and specificity, then the offer earlier in the list is
45// preferred. If no offers match, then defaultOffer is returned.
46func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
47 bestOffer := defaultOffer
48 bestQ := -1.0
49 bestWild := 3
50 specs := header.ParseAccept(r.Header, "Accept")
51 for _, rawOffer := range offers {
52 offer := normalizeOffer(rawOffer)
53 // No Accept header: just return the first offer.
54 if len(specs) == 0 {
55 return rawOffer
56 }
57 for _, spec := range specs {
58 switch {
59 case spec.Q == 0.0:
60 // ignore
61 case spec.Q < bestQ:
62 // better match found
63 case spec.Value == "*/*":
64 if spec.Q > bestQ || bestWild > 2 {
65 bestQ = spec.Q
66 bestWild = 2
67 bestOffer = rawOffer
68 }
69 case strings.HasSuffix(spec.Value, "/*"):
70 if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
71 (spec.Q > bestQ || bestWild > 1) {
72 bestQ = spec.Q
73 bestWild = 1
74 bestOffer = rawOffer
75 }
76 default:
77 if spec.Value == offer &&
78 (spec.Q > bestQ || bestWild > 0) {
79 bestQ = spec.Q
80 bestWild = 0
81 bestOffer = rawOffer
82 }
83 }
84 }
85 }
86 return bestOffer
87}
88
89func normalizeOffers(orig []string) (norm []string) {
90 for _, o := range orig {
91 norm = append(norm, normalizeOffer(o))
92 }
93 return
94}
95
96func normalizeOffer(orig string) string {
97 return strings.SplitN(orig, ";", 2)[0]
98}