ezhttp/request.go
2024-09-11 13:32:52 +02:00

194 lines
4.1 KiB
Go

package ezhttp
import (
"bytes"
"encoding/base64"
"encoding/json"
"io"
"net/http"
urlpkg "net/url"
"strings"
)
type RequestModifier func(r *RequestBuilder) *RequestBuilder
type ValueProvider[T any] func() T
type AuthProvider ValueProvider[string]
type RequestBodyProvider func() (io.Reader, string)
func Request(mods ...RequestModifier) (*http.Request, error) {
r := NewRequestBuilder()
for _, mod := range mods {
r = mod(r)
}
return r.Build()
}
func Template(req *http.Request) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
return NewRequestBuilderFromRequest(req)
}
}
func URL(url string) RequestModifier {
parsedUrl, err := urlpkg.Parse(url)
if err != nil {
panic(err)
}
return func(r *RequestBuilder) *RequestBuilder {
r.URL = parsedUrl
return r
//return Headers("Host", parsedUrl.Host)(r)
}
}
func Scheme(scheme string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.URL.Scheme = scheme
return r
}
}
func Host(host string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.URL.Host = host
return r
}
}
func Path(path string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.URL.Path = path
return r
}
}
func AppendPath(path ...string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.URL = r.URL.JoinPath(path...)
return r
}
}
func Fragment(fragment string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.URL.Fragment = fragment
return r
}
}
func Query(keyValuePairs ...string) RequestModifier {
if len(keyValuePairs)%2 != 0 {
panic("keyValuePairs must have an even length")
}
return func(r *RequestBuilder) *RequestBuilder {
q := r.URL.Query()
for i := 0; i < len(keyValuePairs)-1; i += 2 {
q.Add(keyValuePairs[i], keyValuePairs[i+1])
}
r.URL.RawQuery = q.Encode()
return r
}
}
func QueryMap(query map[string]string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
q := r.URL.Query()
for key, value := range query {
q.Add(key, value)
}
r.URL.RawQuery = q.Encode()
return r
}
}
func Method(method string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
r.Method = method
return r
}
}
func Headers(keyValuePairs ...string) RequestModifier {
if len(keyValuePairs)%2 != 0 {
panic("keyValuePairs must have an even length")
}
return func(r *RequestBuilder) *RequestBuilder {
for i := 0; i < len(keyValuePairs)-1; i += 2 {
r.Header.Add(keyValuePairs[i], keyValuePairs[i+1])
}
return r
}
}
func HeadersMap(headers map[string]string) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
for key, value := range headers {
r.Header.Add(key, value)
}
return r
}
}
func Auth(auth AuthProvider) RequestModifier {
return Headers("Authentication", auth())
}
func Basic(username, password string) AuthProvider {
return func() string {
return "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password))
}
}
func Bearer(token string) AuthProvider {
return func() string {
return "Bearer " + token
}
}
func ContentType(contentType string) RequestModifier {
return Headers("Content-Type", contentType)
}
func Body(bodyProvider RequestBodyProvider) RequestModifier {
return func(r *RequestBuilder) *RequestBuilder {
body, contentType := bodyProvider()
r.Body = body
if contentType != "" && r.Header.Get("Content-Type") != "" {
r.Header.Set("Content-Type", contentType)
}
return r
}
}
func Reader(r io.Reader) RequestBodyProvider {
return func() (io.Reader, string) {
return r, "application/octet-stream"
}
}
func String(s string) RequestBodyProvider {
return func() (io.Reader, string) {
return strings.NewReader(s), "text/plain"
}
}
func Bytes(b []byte) RequestBodyProvider {
return func() (io.Reader, string) {
return bytes.NewReader(b), "application/octet-stream"
}
}
func JSON[T any](value T) RequestBodyProvider {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
if err := json.NewEncoder(buf).Encode(value); err != nil {
panic(err)
}
return func() (io.Reader, string) {
return buf, "application/json"
}
}