Skip to content

Commit

Permalink
feat: net/http/httputilmore: add Endpoint{}
Browse files Browse the repository at this point in the history
  • Loading branch information
grokify committed May 10, 2024
1 parent b2f55b0 commit 721d47e
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
94 changes: 94 additions & 0 deletions net/http/httputilmore/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package httputilmore

import (
"context"
"errors"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)

type Endpoint struct {
Method HTTPMethod
URL *url.URL
}

// ParseEndpoint returns an `Endpoint` upon parsing a string like "POST https://example.com".
// If no method is provided, `GET` is returned. If the string has more than two fields, the lsat
// field is ignored.
func ParseEndpoint(s string) (*Endpoint, error) {
parts := strings.Fields(s)
if len(parts) == 0 {
return nil, errors.New("empty string cannot be parsed as RUL")
} else if len(parts) == 1 {
if u, err := url.Parse(s); err != nil {
return nil, err
} else {
return &Endpoint{
Method: MethodGet,
URL: u,
}, nil
}
} else {
m, err := ParseHTTPMethod(parts[0])
if err != nil {
return nil, err
}
e := Endpoint{
Method: m,
}
if u, err := url.Parse(parts[1]); err != nil {
return nil, err
} else {
e.URL = u
return &e, nil
}
}
}

func ParseRequestEndpoint(r *http.Request) *Endpoint {
if r == nil {
return nil
}
m := strings.ToUpper((strings.TrimSpace(r.Method)))
if m == "" {
m = http.MethodGet
}
return &Endpoint{
Method: HTTPMethod(m),
URL: r.URL,
}
}

func ParseRequestMethodPath(r *http.Request) string {
if r == nil {
return ""
}
m := strings.ToUpper((strings.TrimSpace(r.Method)))
path := r.URL.Path
return m + " " + path
}

// CreateProxyRequest creates a proxy request given a mapping "POST /path" => "POST https://newurl"
func CreateProxyRequest(m map[string]string, r *http.Request) (*httputil.ProxyRequest, error) {
if r == nil {
return nil, nil
}
mp := ParseRequestMethodPath(r)
if v, ok := m[mp]; ok {
ep, err := ParseEndpoint(v)
if err != nil {
return nil, err
}
pr := httputil.ProxyRequest{
In: r,
}
out := r.Clone(context.TODO())
out.Method = string(ep.Method)
out.URL = ep.URL
return &pr, nil
} else {
return nil, nil
}
}
33 changes: 33 additions & 0 deletions net/http/httputilmore/endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package httputilmore

import (
"testing"
)

var parseEndpointTests = []struct {
v string
wantMethod HTTPMethod
wantURL string
}{
{"GET https://example.com", MethodGet, "https://example.com"},
{" PaTcH https://example.com/ ", MethodPatch, "https://example.com/"},
}

func TestParseEndpoint(t *testing.T) {
for _, tt := range parseEndpointTests {
ep, err := ParseEndpoint(tt.v)
if err != nil {
t.Errorf("httputilmore.ParseEndpoint(\"%s\") Error: [%s]",
tt.v, err.Error())
}
if ep.Method != tt.wantMethod {
t.Errorf("httputilmore.ParseEndpoint(\"%s\") Fail Method: want [%s] got [%s]",
tt.v, tt.wantMethod, ep.Method)
}
epURL := ep.URL.String()
if epURL != tt.wantURL {
t.Errorf("httputilmore.ParseEndpoint(\"%s\") Fail URL: want [%s] got [%s]",
tt.v, tt.wantURL, epURL)
}
}
}

0 comments on commit 721d47e

Please sign in to comment.