105 lines
2.2 KiB
Go
105 lines
2.2 KiB
Go
|
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()
|
||
|
}
|