Skip to content

Commit 9cc3c87

Browse files
committed
content type and request
1 parent e41b451 commit 9cc3c87

7 files changed

+213
-157
lines changed

ahttp.go

-8
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,4 @@ type (
2626
Language string
2727
Region string
2828
}
29-
30-
// ContentType is represents request and response content type values
31-
ContentType struct {
32-
Raw string
33-
Mime string
34-
Exts []string
35-
Params map[string]string
36-
}
3729
)

content_type.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm)
2+
// go-aah/aah source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package ahttp
6+
7+
import (
8+
"fmt"
9+
"strings"
10+
)
11+
12+
var (
13+
// ContentTypeHTML HTML content type.
14+
ContentTypeHTML = &ContentType{
15+
Mime: "text/html",
16+
Exts: []string{".html", ".htm"},
17+
Params: map[string]string{
18+
"charset": "utf-8",
19+
},
20+
}
21+
22+
// ContentTypeJSON JSON content type.
23+
ContentTypeJSON = &ContentType{
24+
Mime: "application/json",
25+
Exts: []string{".json"},
26+
Params: map[string]string{
27+
"charset": "utf-8",
28+
},
29+
}
30+
31+
// ContentTypeXML XML content type.
32+
ContentTypeXML = &ContentType{
33+
Mime: "application/xml",
34+
Exts: []string{".xml"},
35+
Params: map[string]string{
36+
"charset": "utf-8",
37+
},
38+
}
39+
)
40+
41+
type (
42+
// ContentType is represents request and response content type values
43+
ContentType struct {
44+
Mime string
45+
Exts []string
46+
Params map[string]string
47+
}
48+
)
49+
50+
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
51+
// Content-Type methods
52+
//___________________________________
53+
54+
// IsEqual method compare give Content-Type string wth instance.
55+
// E.g.:
56+
// contentType.IsEqual("application/json")
57+
func (c *ContentType) IsEqual(contentType string) bool {
58+
return strings.EqualFold(c.Mime, strings.ToLower(contentType))
59+
}
60+
61+
// Charset returns charset of content-type otherwise `defaultCharset` is returned
62+
// For e.g.:
63+
// Content-Type: application/json; charset=utf-8
64+
//
65+
// Method returns `utf-8`
66+
func (c *ContentType) Charset(defaultCharset string) string {
67+
if v, ok := c.Params["charset"]; ok {
68+
return v
69+
}
70+
return defaultCharset
71+
}
72+
73+
// Version returns Accept header version paramater value if present otherwise
74+
// empty string
75+
// For e.g.:
76+
// Accept: application/json; version=2
77+
//
78+
// Method returns `2`
79+
func (c *ContentType) Version() string {
80+
if v, ok := c.Params["version"]; ok {
81+
return v
82+
}
83+
return ""
84+
}
85+
86+
// Raw method returns complete Content-Type composed.
87+
// E.g.: application/json; charset=utf-8; version=2
88+
func (c *ContentType) Raw() string {
89+
raw := c.Mime
90+
for k, v := range c.Params {
91+
raw += fmt.Sprintf("; %s=%s", k, v)
92+
}
93+
return raw
94+
}
95+
96+
// String is stringer interface
97+
func (c *ContentType) String() string {
98+
return c.Raw()
99+
}

content_type_test.go

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm)
2+
// go-aah/aah source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package ahttp
6+
7+
import (
8+
"net/url"
9+
"testing"
10+
11+
"aahframework.org/test/assert"
12+
)
13+
14+
func TestNegotiateContentType(t *testing.T) {
15+
req1 := createRawHTTPRequest(HeaderAccept, "audio/*; q=0.2, audio/basic")
16+
contentType := NegotiateContentType(req1)
17+
assert.Equal(t, "audio/basic", contentType.String())
18+
assert.Equal(t, "audio/basic", contentType.Mime)
19+
assert.Equal(t, "", contentType.Version())
20+
21+
req2 := createRawHTTPRequest(HeaderAccept, "application/json;version=2")
22+
contentType = NegotiateContentType(req2)
23+
assert.Equal(t, "application/json; version=2", contentType.String())
24+
assert.Equal(t, "application/json", contentType.Mime)
25+
assert.Equal(t, "2", contentType.Version())
26+
27+
req3 := createRawHTTPRequest(HeaderAccept, "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c")
28+
contentType = NegotiateContentType(req3)
29+
assert.Equal(t, "text/html", contentType.String())
30+
assert.Equal(t, "text/html", contentType.Mime)
31+
assert.Equal(t, "", contentType.Version())
32+
33+
req4 := createRawHTTPRequest(HeaderAccept, "")
34+
contentType = NegotiateContentType(req4)
35+
assert.Equal(t, "text/html; charset=utf-8", contentType.String())
36+
assert.Equal(t, "text/html", contentType.Mime)
37+
assert.Equal(t, ".html", contentType.Exts[0])
38+
assert.Equal(t, "", contentType.Version())
39+
40+
req := createRawHTTPRequest(HeaderAccept, "application/json")
41+
req.URL, _ = url.Parse("http://localhost:8080/testpath.json")
42+
contentType = NegotiateContentType(req)
43+
assert.Equal(t, "application/json", contentType.Mime)
44+
assert.Equal(t, ".json", contentType.Exts[0])
45+
46+
req = createRawHTTPRequest(HeaderAccept, "application/json")
47+
req.URL, _ = url.Parse("http://localhost:8080/testpath.html")
48+
contentType = NegotiateContentType(req)
49+
assert.Equal(t, "text/html; charset=utf-8", contentType.Mime)
50+
assert.Equal(t, ".html", contentType.Exts[0])
51+
52+
req = createRawHTTPRequest(HeaderAccept, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
53+
contentType = NegotiateContentType(req)
54+
assert.Equal(t, "text/html", contentType.String())
55+
assert.Equal(t, "text/html", contentType.Mime)
56+
assert.Equal(t, "", contentType.Version())
57+
58+
// ParseAccept
59+
req = createRawHTTPRequest(HeaderAccept, "application/json; version=2")
60+
spec := ParseAccept(req, HeaderAccept).MostQualified()
61+
assert.Equal(t, "2", spec.GetParam("version", "1"))
62+
63+
req = createRawHTTPRequest(HeaderAccept, "application/json")
64+
spec = ParseAccept(req, HeaderAccept).MostQualified()
65+
assert.Equal(t, "1", spec.GetParam("version", "1"))
66+
67+
req = createRawHTTPRequest(HeaderAccept, "application/json; version")
68+
spec = ParseAccept(req, HeaderAccept).MostQualified()
69+
assert.Equal(t, "", spec.GetParam("version", "1"))
70+
71+
}
72+
73+
func TestParseContentType(t *testing.T) {
74+
req1 := createRawHTTPRequest(HeaderContentType, "text/html; charset=utf-8")
75+
contentType := ParseContentType(req1)
76+
assert.Equal(t, "text/html", contentType.Mime)
77+
assert.Equal(t, "text/html; charset=utf-8", contentType.String())
78+
assert.Equal(t, "utf-8", contentType.Charset("iso-8859-1"))
79+
80+
req2 := createRawHTTPRequest(HeaderContentType, "text/html")
81+
contentType = ParseContentType(req2)
82+
assert.Equal(t, "text/html", contentType.Mime)
83+
assert.Equal(t, "text/html", contentType.String())
84+
assert.Equal(t, "iso-8859-1", contentType.Charset("iso-8859-1"))
85+
86+
req3 := createRawHTTPRequest(HeaderContentType, "application/json")
87+
contentType = ParseContentType(req3)
88+
assert.Equal(t, "application/json", contentType.Mime)
89+
assert.Equal(t, "application/json", contentType.String())
90+
assert.Equal(t, "", contentType.Charset(""))
91+
92+
req4 := createRawHTTPRequest(HeaderContentType, "")
93+
contentType = ParseContentType(req4)
94+
assert.Equal(t, "text/html", contentType.Mime)
95+
assert.Equal(t, "text/html; charset=utf-8", contentType.String())
96+
assert.Equal(t, ".html", contentType.Exts[0])
97+
98+
req5 := createRawHTTPRequest(HeaderContentType, "text/html;charset")
99+
contentType = ParseContentType(req5)
100+
assert.Equal(t, "text/html", contentType.Mime)
101+
assert.Equal(t, "text/html; charset=", contentType.String())
102+
assert.Equal(t, "", contentType.Charset("iso-8859-1"))
103+
}

header.go

+2-55
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ func NegotiateContentType(req *http.Request) *ContentType {
8585
switch ext {
8686
case ".html", ".htm", ".json", ".js", ".xml", ".txt":
8787
mimeType := mime.TypeByExtension(ext)
88-
raw := mimeType
8988
return &ContentType{
90-
Raw: raw,
9189
Mime: mimeType,
9290
Exts: []string{ext},
9391
Params: make(map[string]string),
@@ -97,13 +95,12 @@ func NegotiateContentType(req *http.Request) *ContentType {
9795
// 2) From Accept header
9896
spec := ParseAccept(req, HeaderAccept).MostQualified()
9997
if spec == nil {
100-
return htmlContentType()
98+
return ContentTypeHTML
10199
}
102100

103101
exts, _ := mime.ExtensionsByType(spec.Value)
104102

105103
return &ContentType{
106-
Raw: spec.Raw,
107104
Mime: spec.Value,
108105
Exts: exts,
109106
Params: spec.Params,
@@ -130,7 +127,7 @@ func ParseContentType(req *http.Request) *ContentType {
130127
contentType := req.Header.Get(HeaderContentType)
131128

132129
if ess.IsStrEmpty(contentType) {
133-
return htmlContentType()
130+
return ContentTypeHTML
134131
}
135132

136133
values := strings.Split(strings.ToLower(contentType), ";")
@@ -148,7 +145,6 @@ func ParseContentType(req *http.Request) *ContentType {
148145
exts, _ := mime.ExtensionsByType(ctype)
149146

150147
return &ContentType{
151-
Raw: contentType,
152148
Mime: ctype,
153149
Exts: exts,
154150
Params: params,
@@ -249,40 +245,6 @@ func (l *Locale) String() string {
249245
return l.Raw
250246
}
251247

252-
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
253-
// Content-Type methods
254-
//___________________________________
255-
256-
// Charset returns charset of content-type otherwise `defaultCharset` is returned
257-
// For e.g.:
258-
// Content-Type: application/json; charset=utf-8
259-
//
260-
// Method returns `utf-8`
261-
func (c *ContentType) Charset(defaultCharset string) string {
262-
if v, ok := c.Params["charset"]; ok {
263-
return v
264-
}
265-
return defaultCharset
266-
}
267-
268-
// Version returns Accept header version paramater value if present otherwise
269-
// empty string
270-
// For e.g.:
271-
// Accept: application/json; version=2
272-
//
273-
// Method returns `2`
274-
func (c *ContentType) Version() string {
275-
if v, ok := c.Params["version"]; ok {
276-
return v
277-
}
278-
return ""
279-
}
280-
281-
// String is stringer interface
282-
func (c *ContentType) String() string {
283-
return c.Raw
284-
}
285-
286248
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
287249
// AcceptSpecs methods
288250
//___________________________________
@@ -322,18 +284,3 @@ func (specs AcceptSpecs) Swap(i, j int) {
322284
func (specs AcceptSpecs) Less(i, j int) bool {
323285
return specs[i].Q > specs[j].Q
324286
}
325-
326-
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
327-
// Unexported methods
328-
//___________________________________
329-
330-
func htmlContentType() *ContentType {
331-
return &ContentType{
332-
Raw: "text/html; charset=utf-8",
333-
Mime: "text/html",
334-
Exts: []string{".html"},
335-
Params: map[string]string{
336-
"charset": "utf-8",
337-
},
338-
}
339-
}

0 commit comments

Comments
 (0)