Merge branch 'master' into workflow-dev

This commit is contained in:
Ryan Lettieri 2022-10-10 09:53:15 -06:00 committed by GitHub
commit d4bc5361e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 142 additions and 12 deletions

View File

@ -1,16 +1,34 @@
package httputils
import "net/http"
import (
"net/http"
"net/url"
)
// RequestURI returns the path and query string (if present) from the request
// For example: `/foo` or `/foo?hello=world`
func RequestURI(r *http.Request) string {
u := r.URL.Path
if len(u) == 0 || u[0] != '/' {
u = "/" + u
u := r.URL
result := u.EscapedPath()
if result == "" {
result = "/"
}
if len(r.URL.RawQuery) > 0 {
u += "?" + r.URL.RawQuery
if u.ForceQuery || u.RawQuery != "" {
result += "?" + u.RawQuery
}
return u
return result
}
// SetRequestURI replaces the path and query string (if present) from the
// request with the input. For example: `/foo` or `/foo?hello=world`
func SetRequestURI(r *http.Request, uri string) error {
if u, err := url.ParseRequestURI(uri); err != nil {
return err
} else { // copy the URI without overwriting the host, etc.
r.URL.RawPath = u.RawPath
r.URL.Path = u.Path
r.URL.ForceQuery = u.ForceQuery
r.URL.RawQuery = u.RawQuery
}
return nil
}

View File

@ -0,0 +1,114 @@
package httputils
import (
"net/http"
"net/url"
"testing"
)
func TestRequestURI(t *testing.T) {
tests := []struct {
name string
url *url.URL
expectedURI string
}{
{
name: "coerces empty path to slash",
url: &url.URL{
Scheme: "http",
Host: "example.com",
Path: "",
},
expectedURI: "/",
},
{
name: "encodes space",
url: &url.URL{
Scheme: "http",
Host: "example.com",
Path: "/a b",
},
expectedURI: "/a%20b",
},
{
name: "encodes query",
url: &url.URL{
Scheme: "http",
Host: "example.com",
Path: "/a b",
RawQuery: "q=go+language",
},
expectedURI: "/a%20b?q=go+language",
},
{
name: "double slash path",
url: &url.URL{
Scheme: "http",
Host: "example.com",
Path: "//foo",
},
expectedURI: "//foo",
},
{
name: "empty query",
url: &url.URL{
Scheme: "http",
Host: "example.com",
Path: "/foo",
ForceQuery: true,
},
expectedURI: "/foo?",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
r := &http.Request{URL: tc.url}
if want, have := tc.expectedURI, RequestURI(r); want != have {
t.Errorf("unexpected uri, want: %s, have: %s", want, have)
}
})
}
}
func Test_SetRequestURI(t *testing.T) {
tests := []struct {
name string
expectedURI string
}{
{
name: "coerces empty path to slash",
expectedURI: "/",
},
{
name: "encodes space",
expectedURI: "/a%20b",
},
{
name: "encodes query",
expectedURI: "/a%20b?q=go+language",
},
{
name: "double slash path",
expectedURI: "//foo",
},
{
name: "empty query",
expectedURI: "/foo?",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
r := &http.Request{URL: &url.URL{}}
if err := SetRequestURI(r, tc.expectedURI); err != nil {
t.Error(err)
}
if want, have := tc.expectedURI, r.URL.RequestURI(); want != have {
t.Errorf("unexpected uri, want: %s, have: %s", want, have)
}
})
}
}

View File

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"os"
"runtime"
"strconv"
@ -178,15 +177,14 @@ func (rh *wapcRequestHandler) requestHandler(next http.Handler) http.Handler {
})
}
// handle is like fasthttp.RequestHandler, except it accepts a waPC instance
// and returns an error.
// handle is like http.Handler, except it accepts a waPC instance and returns
// an error.
func (rh *wapcRequestHandler) handle(r *http.Request, instance wapc.Instance) error {
if uri, err := instance.Invoke(ctx, "rewrite", []byte(httputils.RequestURI(r))); err != nil {
return err
} else {
r.URL, _ = url.Parse(string(uri))
return httputils.SetRequestURI(r, string(uri))
}
return nil
}
// Close implements io.Closer