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