@@ -2,11 +2,11 @@ package header
22
33import (
44 "io"
5+ "mime"
56 "net/http"
67 "strings"
78
89 "github.com/rickb777/acceptable/headername"
9- "github.com/rickb777/acceptable/internal"
1010)
1111
1212// ContentType is a media type as defined in RFC-2045, RFC-2046, RFC-2231
@@ -15,11 +15,26 @@ import (
1515// There may also be parameters (e.g. "charset=utf-8") and extension values.
1616type ContentType struct {
1717 // Type and Subtype carry the media type, e.g. "text" and "html"
18- Type , Subtype string
18+ MediaType string
1919 // Params and Extensions hold optional parameter information
2020 Params []KV
2121}
2222
23+ func (ct ContentType ) Split () (string , string ) {
24+ t , s , _ := strings .Cut (ct .MediaType , "/" )
25+ return t , s
26+ }
27+
28+ func (ct ContentType ) Type () string {
29+ t , _ := ct .Split ()
30+ return t
31+ }
32+
33+ func (ct ContentType ) Subtype () string {
34+ _ , s := ct .Split ()
35+ return s
36+ }
37+
2338// AsMediaRange converts this ContentType to a MediaRange.
2439// The default quality should be 1.
2540func (ct ContentType ) AsMediaRange (quality float64 ) MediaRange {
@@ -44,33 +59,32 @@ func (ct ContentType) AsMediaRange(quality float64) MediaRange {
4459//
4560// where "*" is a wildcard.
4661func (ct ContentType ) IsTextual () bool {
47- if ct .Type == "text" {
62+ t , s := ct .Split ()
63+ if t == "text" {
4864 return true
4965 }
5066
51- if ct . Type == "application" {
52- return ct . Subtype == "json" ||
53- ct . Subtype == "xml" ||
54- strings .HasSuffix (ct . Subtype , "+xml" ) ||
55- strings .HasSuffix (ct . Subtype , "+json" )
67+ if t == "application" {
68+ return s == "json" ||
69+ s == "xml" ||
70+ strings .HasSuffix (s , "+xml" ) ||
71+ strings .HasSuffix (s , "+json" )
5672 }
5773
58- if ct . Type == "model" {
59- return strings .HasSuffix (ct . Subtype , "+xml" ) ||
60- strings .HasSuffix (ct . Subtype , "+json" )
74+ if t == "model" {
75+ return strings .HasSuffix (s , "+xml" ) ||
76+ strings .HasSuffix (s , "+json" )
6177 }
6278
63- if ct . Type == "image" || ct . Type == "message" {
64- return strings .HasSuffix (ct . Subtype , "+xml" )
79+ if t == "image" || t == "message" {
80+ return strings .HasSuffix (s , "+xml" )
6581 }
6682
6783 return false
6884}
6985
7086func (ct ContentType ) writeTo (w io.StringWriter ) {
71- w .WriteString (ct .Type )
72- w .WriteString ("/" )
73- w .WriteString (ct .Subtype )
87+ w .WriteString (ct .MediaType )
7488 for _ , p := range ct .Params {
7589 w .WriteString (";" )
7690 w .WriteString (p .Key )
@@ -85,7 +99,7 @@ func (ct ContentType) String() string {
8599 return buf .String ()
86100}
87101
88- var starStar = ContentType {Type : "*" , Subtype : " *" }
102+ var starStar = ContentType {MediaType : "*/ *" }
89103
90104// ParseContentTypeFromHeaders gets the "Content-Type" header and returns
91105// its parsed value.
@@ -103,34 +117,17 @@ func ParseContentType(ct string) ContentType {
103117 return starStar
104118 }
105119
106- valueAndParams := Split (ct , ";" ).TrimSpace ()
107- t , s := internal .Split1 (valueAndParams [0 ], '/' )
108- return contentTypeOf (t , s , valueAndParams [1 :])
109- }
110-
111- // contentTypeOf builds a content type value with optional parameters.
112- // The parameters are passed in as literal strings, e.g. "charset=utf-8".
113- func contentTypeOf (typ , subtype string , paramKV []string ) ContentType {
114- if typ == "" {
120+ mt , params , err := mime .ParseMediaType (ct )
121+ if err != nil {
115122 return starStar
116123 }
117124
118- if subtype == "" {
119- subtype = "*"
120- }
121-
122- var params []KV
123- if len (paramKV ) > 0 {
124- params = make ([]KV , 0 , len (paramKV ))
125- for _ , p := range paramKV {
126- k , v := internal .Split1 (p , '=' )
127- params = append (params , KV {Key : k , Value : v })
125+ var paramsKV []KV
126+ if len (params ) > 0 {
127+ paramsKV = make ([]KV , 0 , len (params ))
128+ for k , v := range params {
129+ paramsKV = append (paramsKV , KV {Key : k , Value : v })
128130 }
129131 }
130-
131- return ContentType {
132- Type : typ ,
133- Subtype : subtype ,
134- Params : params ,
135- }
132+ return ContentType {MediaType : mt , Params : paramsKV }
136133}
0 commit comments