1
1
package accept
2
2
3
3
import (
4
+ "log"
4
5
"mime"
6
+ "strings"
5
7
6
8
"github.com/WICG/webpackage/go/signedexchange/version"
7
9
"github.com/ampproject/amppackager/packager/util"
@@ -18,23 +20,61 @@ const SxgContentType = "application/signed-exchange;v=" + AcceptedSxgVersion
18
20
// signedexchange library.
19
21
var SxgVersion = version .Version1b3
20
22
23
+ // Tokenize a comma-separated string of accept patterns into a slice
24
+ func tokenize (accept string ) []string {
25
+ var tokens []string
26
+ acceptLen := len (accept )
27
+ if acceptLen == 0 {
28
+ return tokens
29
+ }
30
+
31
+ inQuotes := false
32
+ startIndex := 0
33
+ for i := 0 ; i < acceptLen ; i ++ {
34
+ char := accept [i ]
35
+ switch char {
36
+ case '"' :
37
+ inQuotes = ! inQuotes
38
+ case ',' :
39
+ if ! inQuotes {
40
+ tokens = append (tokens , util .TrimHeaderValue (accept [startIndex :i ]))
41
+ startIndex = i + 1
42
+ }
43
+ case '\\' :
44
+ if ! inQuotes {
45
+ log .Printf ("unable to parse Accept header: %s" , accept )
46
+ return []string {}
47
+ }
48
+ i ++
49
+ }
50
+ }
51
+ tokens = append (tokens , util .TrimHeaderValue (accept [startIndex :]))
52
+ return tokens
53
+ }
54
+
55
+ // Determine whether a version specified by the accept header matches the
56
+ // version of signed exchange output by the packager
57
+ func hasMatchingSxgVersion (versions []string ) bool {
58
+ for _ , version := range versions {
59
+ if version == AcceptedSxgVersion {
60
+ return true
61
+ }
62
+ }
63
+ return false
64
+ }
65
+
21
66
// True if the given Accept header is one that the packager can satisfy. It
22
67
// must contain application/signed-exchange;v=$V so that the packager knows
23
68
// whether or not it can supply the correct version. "" and "*/*" are not
24
69
// satisfiable, for this reason.
25
70
func CanSatisfy (accept string ) bool {
26
- // There is an edge case on which this comma-splitting fails:
27
- // Accept: application/signed-exchange;junk="some,thing";v=b2
28
- // However, in practice, browsers don't send media types with quoted
29
- // commas in them:
30
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values
31
- // So we'll live with this deficiency for the sake of not forking
32
- // mime.ParseMediaType.
33
- types := util .Comma .Split (accept , - 1 )
71
+ types := tokenize (accept )
34
72
for _ , mediaRange := range types {
35
73
mediatype , params , err := mime .ParseMediaType (mediaRange )
36
- if err == nil && mediatype == "application/signed-exchange" && params ["v" ] == AcceptedSxgVersion {
37
- return true
74
+ if err == nil && mediatype == "application/signed-exchange" {
75
+ if hasMatchingSxgVersion (strings .Split (params ["v" ], "," )) {
76
+ return true
77
+ }
38
78
}
39
79
}
40
80
return false
0 commit comments