mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-17 23:14:21 +01:00
230 lines
6.0 KiB
Go
230 lines
6.0 KiB
Go
package routeApi
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestPlayground(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
tests := []struct {
|
|
name string
|
|
request PlaygroundRequest
|
|
wantStatusCode int
|
|
checkResponse func(t *testing.T, resp PlaygroundResponse)
|
|
}{
|
|
{
|
|
name: "simple path matching rule",
|
|
request: PlaygroundRequest{
|
|
Rules: []RawRule{
|
|
{
|
|
Name: "test rule",
|
|
On: "path /api",
|
|
Do: "pass",
|
|
},
|
|
},
|
|
MockRequest: MockRequest{
|
|
Method: "GET",
|
|
Path: "/api",
|
|
},
|
|
},
|
|
wantStatusCode: http.StatusOK,
|
|
checkResponse: func(t *testing.T, resp PlaygroundResponse) {
|
|
if len(resp.ParsedRules) != 1 {
|
|
t.Errorf("expected 1 parsed rule, got %d", len(resp.ParsedRules))
|
|
}
|
|
if resp.ParsedRules[0].ValidationError != nil {
|
|
t.Errorf("expected rule to be valid, got error: %v", resp.ParsedRules[0].ValidationError)
|
|
}
|
|
if len(resp.MatchedRules) != 1 || resp.MatchedRules[0] != "test rule" {
|
|
t.Errorf("expected matched rules to be ['test rule'], got %v", resp.MatchedRules)
|
|
}
|
|
if !resp.UpstreamCalled {
|
|
t.Error("expected upstream to be called")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "header matching rule",
|
|
request: PlaygroundRequest{
|
|
Rules: []RawRule{
|
|
{
|
|
Name: "check user agent",
|
|
On: "header User-Agent Chrome",
|
|
Do: "error 403 Forbidden",
|
|
},
|
|
},
|
|
MockRequest: MockRequest{
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string][]string{
|
|
"User-Agent": {"Chrome"},
|
|
},
|
|
},
|
|
},
|
|
wantStatusCode: http.StatusOK,
|
|
checkResponse: func(t *testing.T, resp PlaygroundResponse) {
|
|
if len(resp.ParsedRules) != 1 {
|
|
t.Errorf("expected 1 parsed rule, got %d", len(resp.ParsedRules))
|
|
}
|
|
if resp.ParsedRules[0].ValidationError != nil {
|
|
t.Errorf("expected rule to be valid, got error: %v", resp.ParsedRules[0].ValidationError)
|
|
}
|
|
if len(resp.MatchedRules) != 1 {
|
|
t.Errorf("expected 1 matched rule, got %d", len(resp.MatchedRules))
|
|
}
|
|
if resp.FinalResponse.StatusCode != http.StatusForbidden {
|
|
t.Errorf("expected status 403, got %d", resp.FinalResponse.StatusCode)
|
|
}
|
|
if resp.UpstreamCalled {
|
|
t.Error("expected upstream not to be called")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "invalid rule syntax",
|
|
request: PlaygroundRequest{
|
|
Rules: []RawRule{
|
|
{
|
|
Name: "bad rule",
|
|
On: "invalid_checker something",
|
|
Do: "pass",
|
|
},
|
|
},
|
|
MockRequest: MockRequest{
|
|
Method: "GET",
|
|
Path: "/",
|
|
},
|
|
},
|
|
wantStatusCode: http.StatusOK,
|
|
checkResponse: func(t *testing.T, resp PlaygroundResponse) {
|
|
if len(resp.ParsedRules) != 1 {
|
|
t.Errorf("expected 1 parsed rule, got %d", len(resp.ParsedRules))
|
|
}
|
|
if resp.ParsedRules[0].ValidationError == nil {
|
|
t.Error("expected validation error to be set")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "rewrite path rule",
|
|
request: PlaygroundRequest{
|
|
Rules: []RawRule{
|
|
{
|
|
Name: "rewrite rule",
|
|
On: "path glob(/api/*)",
|
|
Do: "rewrite /api/ /v1/",
|
|
},
|
|
},
|
|
MockRequest: MockRequest{
|
|
Method: "GET",
|
|
Path: "/api/users",
|
|
},
|
|
},
|
|
wantStatusCode: http.StatusOK,
|
|
checkResponse: func(t *testing.T, resp PlaygroundResponse) {
|
|
if len(resp.ParsedRules) != 1 {
|
|
t.Errorf("expected 1 parsed rule, got %d", len(resp.ParsedRules))
|
|
}
|
|
if resp.ParsedRules[0].ValidationError != nil {
|
|
t.Errorf("expected rule to be valid, got error: %v", resp.ParsedRules[0].ValidationError)
|
|
}
|
|
if !resp.UpstreamCalled {
|
|
t.Error("expected upstream to be called")
|
|
}
|
|
if resp.FinalRequest.Path != "/v1/users" {
|
|
t.Errorf("expected path to be rewritten to /v1/users, got %s", resp.FinalRequest.Path)
|
|
}
|
|
// Note: matched rules tracking has limitations with fresh ResponseModifier
|
|
// The important thing is that the rewrite actually worked
|
|
},
|
|
},
|
|
{
|
|
name: "method matching rule",
|
|
request: PlaygroundRequest{
|
|
Rules: []RawRule{
|
|
{
|
|
Name: "block POST",
|
|
On: "method POST",
|
|
Do: `error "405" "Method Not Allowed"`,
|
|
},
|
|
},
|
|
MockRequest: MockRequest{
|
|
Method: "POST",
|
|
Path: "/api",
|
|
},
|
|
},
|
|
wantStatusCode: http.StatusOK,
|
|
checkResponse: func(t *testing.T, resp PlaygroundResponse) {
|
|
if resp.ParsedRules[0].ValidationError != nil {
|
|
t.Errorf("expected rule to be valid, got error: %v", resp.ParsedRules[0].ValidationError)
|
|
}
|
|
if len(resp.MatchedRules) != 1 {
|
|
t.Errorf("expected 1 matched rule, got %d", len(resp.MatchedRules))
|
|
}
|
|
if resp.FinalResponse.StatusCode != http.StatusMethodNotAllowed {
|
|
t.Errorf("expected status 405, got %d", resp.FinalResponse.StatusCode)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Create request
|
|
body, _ := json.Marshal(tt.request)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/route/playground", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
// Create response recorder
|
|
w := httptest.NewRecorder()
|
|
|
|
// Create gin context
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = req
|
|
|
|
// Call handler
|
|
Playground(c)
|
|
|
|
// Check status code
|
|
if w.Code != tt.wantStatusCode {
|
|
t.Errorf("expected status code %d, got %d", tt.wantStatusCode, w.Code)
|
|
}
|
|
|
|
respAny, ok := c.Get("response")
|
|
if !ok {
|
|
t.Fatalf("expected response to be set")
|
|
}
|
|
resp := respAny.(PlaygroundResponse)
|
|
|
|
// Run custom checks
|
|
if tt.checkResponse != nil {
|
|
tt.checkResponse(t, resp)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPlaygroundInvalidRequest(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/route/playground", bytes.NewReader([]byte(`{}`)))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = req
|
|
|
|
Playground(c)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, w.Code)
|
|
}
|
|
}
|