initial commits
parent
31110d58c2
commit
33ffaa1ad7
|
@ -0,0 +1,104 @@
|
|||
package httpaccept
|
||||
|
||||
import (
|
||||
"sourcecode.social/reiver/go-httpaccept/mediarange"
|
||||
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HTTPAccept represents the values of the Accept headers of an HTTP request.
|
||||
//
|
||||
// Note that an HTTP request can have multople Accept headers.
|
||||
type HTTPAccept struct {
|
||||
mediaranges []mediarange.MediaRange
|
||||
}
|
||||
|
||||
// Create creates an HTTPAccept.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// // Accept: application/activity+json
|
||||
// accept := httpaccept.Create(
|
||||
// mediarange.Create("application", "activity+json"), // application/activity+json
|
||||
// )
|
||||
//
|
||||
// // Accept: image/png,image/gif
|
||||
// accept := httpaccept.Create(
|
||||
// mediarange.Create("image", "png"), // image/png
|
||||
// mediarange.Create("image", "gif"), // image/gif
|
||||
// )
|
||||
func Create(mediaranges ...mediarange.MediaRange) HTTPAccept {
|
||||
return HTTPAccept{
|
||||
mediaranges:mediaranges,
|
||||
}
|
||||
}
|
||||
|
||||
// Negotiate figures out if there is an acceptable media-type, and if there is returns the "best" one.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var accept httpaccept.HTTPAccept
|
||||
//
|
||||
// // ...
|
||||
//
|
||||
// contentType, err := accept.Negotiate("text/gemini", "text/html", "application/activity+json")
|
||||
func (receiver HTTPAccept) Negotiate(mediatypes ...string) (string, error) {
|
||||
|
||||
var temp []string
|
||||
|
||||
{
|
||||
temp, mediatypes = mediatypes, nil
|
||||
|
||||
for _, mediatype := range temp {
|
||||
|
||||
a := strings.SplitN(mediatype, ";", 2)
|
||||
if len(a) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
mediatypes = append(mediatypes, a[0])
|
||||
}
|
||||
}
|
||||
|
||||
for _, mediarange := range receiver.mediaranges {
|
||||
|
||||
for _, mediatype := range mediatypes {
|
||||
|
||||
if mediarange.Match(mediatype) {
|
||||
return mediatype, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", internalNotAcceptable{temp}
|
||||
}
|
||||
|
||||
// String returns the serialized HTTP Accept header.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// // "Accept: text/html,application/xhtml+xml\r\n"
|
||||
// s := httpaccept.Create(mediarange.Create("text", "html"), mediarange.Create("application","xhtml+xml")).String()
|
||||
func (receiver HTTPAccept) String() string {
|
||||
var mediaranges []mediarange.MediaRange = receiver.mediaranges
|
||||
|
||||
if len(mediaranges) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var buffer strings.Builder
|
||||
{
|
||||
buffer.WriteString("Accept: ")
|
||||
for i, mediarange := range receiver.mediaranges {
|
||||
|
||||
if 0 != i {
|
||||
buffer.WriteRune(',')
|
||||
}
|
||||
buffer.WriteString(mediarange.String())
|
||||
}
|
||||
buffer.WriteString("\r\n")
|
||||
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package httpaccept_test
|
||||
|
||||
import (
|
||||
"sourcecode.social/reiver/go-httpaccept"
|
||||
"sourcecode.social/reiver/go-httpaccept/mediarange"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPAccept_String(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
HTTPAccept httpaccept.HTTPAccept
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(),
|
||||
Expected: "",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(mediarange.Create("*", "*")),
|
||||
Expected: "Accept: */*"+"\r\n",
|
||||
},
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(mediarange.Create("text", "html"), mediarange.Create("*", "*")),
|
||||
Expected: "Accept: text/html,*/*"+"\r\n",
|
||||
},
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(mediarange.Create("text", "html"), mediarange.Create("application", "xhtml+xml"), mediarange.Create("*", "*")),
|
||||
Expected: "Accept: text/html,application/xhtml+xml,*/*"+"\r\n",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(mediarange.Create("application", "activity+json")),
|
||||
Expected: "Accept: application/activity+json"+"\r\n",
|
||||
},
|
||||
{
|
||||
HTTPAccept: httpaccept.Create(mediarange.Create("application", "activity+json"), mediarange.Create("application", "json")),
|
||||
Expected: "Accept: application/activity+json,application/json"+"\r\n",
|
||||
},
|
||||
}
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
actual := test.HTTPAccept.String()
|
||||
expected := test.Expected
|
||||
|
||||
if expected != actual {
|
||||
t.Errorf("For test #%d, the actual (serialized) stringer value is not what was expected.", testNumber)
|
||||
t.Logf("HTTP-ACCEPT: %#v", test.HTTPAccept)
|
||||
t.Logf("EXPECTED: %q", expected)
|
||||
t.Logf("ACTUAL: %q", actual)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue