-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnegotiator.go
104 lines (85 loc) · 3.35 KB
/
negotiator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright 2020 Guoyao Wu. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package negotiator
import (
"net/http"
"net/textproto"
"strings"
)
// HeaderAcceptCharset is `Accept-Charset`
var HeaderAcceptCharset = textproto.CanonicalMIMEHeaderKey("Accept-Charset")
// HeaderAcceptEncoding is `Accept-Encoding`
var HeaderAcceptEncoding = textproto.CanonicalMIMEHeaderKey("Accept-Encoding")
// HeaderAcceptLanguage is `Accept-Language`
var HeaderAcceptLanguage = textproto.CanonicalMIMEHeaderKey("Accept-Language")
// HeaderAccept is `Accept`
var HeaderAccept = textproto.CanonicalMIMEHeaderKey("Accept")
// Negotiator gets the negotiation info from http header
type Negotiator struct {
Header http.Header
}
// New creates a Negotiator instance from a header object.
func New(header http.Header) *Negotiator {
return &Negotiator{header}
}
// Charset gets the most preferred charset from a list of available charsets.
func (n *Negotiator) Charset(available ...string) string {
return getMostPreferred(n.Charsets(available...))
}
// Charsets gets an array of preferred charsets ordered by priority from a list
// of available charsets.
func (n *Negotiator) Charsets(available ...string) []string {
// RFC 2616 sec 14.2: no header = *
return PreferredCharsets(getAccept(n.Header, HeaderAcceptCharset, "*"), available...)
}
// Encoding gets the most preferred encoding from a list of available encodings.
func (n *Negotiator) Encoding(available ...string) string {
return getMostPreferred(n.Encodings(available...))
}
// Encodings gets an array of preferred encodings ordered by priority from
// a list of available encodings.
func (n *Negotiator) Encodings(available ...string) []string {
// RFC 2616 sec 14.2: no header = *
return PreferredEncodings(getAccept(n.Header, HeaderAcceptEncoding, "*"), available...)
}
// Language gets the most preferred language from a list of available languages.
func (n *Negotiator) Language(available ...string) string {
return getMostPreferred(n.Languages(available...))
}
// Languages gets an array of preferred languages ordered by priority from a list
// of available languages.
func (n *Negotiator) Languages(available ...string) []string {
// RFC 2616 sec 14.2: no header = *
return PreferredLanguages(getAccept(n.Header, HeaderAcceptLanguage, "*"), available...)
}
// MediaType gets the most preferred media type from a list of available media types.
func (n *Negotiator) MediaType(available ...string) string {
return getMostPreferred(n.MediaTypes(available...))
}
// MediaTypes gets an array of preferred mediaTypes ordered by priority from a list
// of available media types.
func (n *Negotiator) MediaTypes(available ...string) []string {
// RFC 2616 sec 14.2: no header = */*
return PreferredMediaTypes(getAccept(n.Header, HeaderAccept, "*/*"), available...)
}
func getMostPreferred(accepts []string) string {
if len(accepts) == 0 {
return ""
}
return accepts[0]
}
func getAccept(h http.Header, key, defaultValue string) string {
accept, values := defaultValue, getHeaderValues(h, key)
if values != nil {
accept = strings.Join(values, ",")
}
return accept
}
// The patch of http.Header.Values for go version lower than 1.4
func getHeaderValues(h http.Header, key string) []string {
if h == nil {
return nil
}
return h[textproto.CanonicalMIMEHeaderKey(key)]
}