214 lines
4.7 KiB
Go
214 lines
4.7 KiB
Go
package runtime_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
|
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
|
)
|
|
|
|
func TestMuxServeHTTP(t *testing.T) {
|
|
type stubPattern struct {
|
|
method string
|
|
ops []int
|
|
pool []string
|
|
verb string
|
|
}
|
|
for _, spec := range []struct {
|
|
patterns []stubPattern
|
|
|
|
reqMethod string
|
|
reqPath string
|
|
headers map[string]string
|
|
|
|
respStatus int
|
|
respContent string
|
|
}{
|
|
{
|
|
patterns: nil,
|
|
reqMethod: "GET",
|
|
reqPath: "/",
|
|
respStatus: http.StatusNotFound,
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "GET",
|
|
reqPath: "/foo",
|
|
respStatus: http.StatusOK,
|
|
respContent: "GET /foo",
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "GET",
|
|
reqPath: "/bar",
|
|
respStatus: http.StatusNotFound,
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpPush), 0},
|
|
},
|
|
},
|
|
reqMethod: "GET",
|
|
reqPath: "/foo",
|
|
respStatus: http.StatusOK,
|
|
respContent: "GET /foo",
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
{
|
|
method: "POST",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "POST",
|
|
reqPath: "/foo",
|
|
respStatus: http.StatusOK,
|
|
respContent: "POST /foo",
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "DELETE",
|
|
reqPath: "/foo",
|
|
respStatus: http.StatusMethodNotAllowed,
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "POST",
|
|
reqPath: "/foo",
|
|
headers: map[string]string{
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
},
|
|
respStatus: http.StatusOK,
|
|
respContent: "GET /foo",
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
{
|
|
method: "POST",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "POST",
|
|
reqPath: "/foo",
|
|
headers: map[string]string{
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"X-HTTP-Method-Override": "GET",
|
|
},
|
|
respStatus: http.StatusOK,
|
|
respContent: "GET /foo",
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "GET",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
},
|
|
},
|
|
reqMethod: "POST",
|
|
reqPath: "/foo",
|
|
headers: map[string]string{
|
|
"Content-Type": "application/json",
|
|
},
|
|
respStatus: http.StatusMethodNotAllowed,
|
|
},
|
|
{
|
|
patterns: []stubPattern{
|
|
{
|
|
method: "POST",
|
|
ops: []int{int(utilities.OpLitPush), 0},
|
|
pool: []string{"foo"},
|
|
verb: "bar",
|
|
},
|
|
},
|
|
reqMethod: "POST",
|
|
reqPath: "/foo:bar",
|
|
headers: map[string]string{
|
|
"Content-Type": "application/json",
|
|
},
|
|
respStatus: http.StatusOK,
|
|
respContent: "POST /foo:bar",
|
|
},
|
|
} {
|
|
mux := runtime.NewServeMux()
|
|
for _, p := range spec.patterns {
|
|
func(p stubPattern) {
|
|
pat, err := runtime.NewPattern(1, p.ops, p.pool, p.verb)
|
|
if err != nil {
|
|
t.Fatalf("runtime.NewPattern(1, %#v, %#v, %q) failed with %v; want success", p.ops, p.pool, p.verb, err)
|
|
}
|
|
mux.Handle(p.method, pat, func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
|
|
fmt.Fprintf(w, "%s %s", p.method, pat.String())
|
|
})
|
|
}(p)
|
|
}
|
|
|
|
url := fmt.Sprintf("http://host.example%s", spec.reqPath)
|
|
r, err := http.NewRequest(spec.reqMethod, url, bytes.NewReader(nil))
|
|
if err != nil {
|
|
t.Fatalf("http.NewRequest(%q, %q, nil) failed with %v; want success", spec.reqMethod, url, err)
|
|
}
|
|
for name, value := range spec.headers {
|
|
r.Header.Set(name, value)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
mux.ServeHTTP(w, r)
|
|
|
|
if got, want := w.Code, spec.respStatus; got != want {
|
|
t.Errorf("w.Code = %d; want %d; patterns=%v; req=%v", got, want, spec.patterns, r)
|
|
}
|
|
if spec.respContent != "" {
|
|
if got, want := w.Body.String(), spec.respContent; got != want {
|
|
t.Errorf("w.Body = %q; want %q; patterns=%v; req=%v", got, want, spec.patterns, r)
|
|
}
|
|
}
|
|
}
|
|
}
|