You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2021/02/25 15:15:15 UTC
[apisix-dashboard] branch master updated: feat(be): Online debug
function adds support for transfer files (#1465)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new e51323f feat(be): Online debug function adds support for transfer files (#1465)
e51323f is described below
commit e51323fccf8b7bf5490f3e59319bb1c10ea03c5f
Author: JinChen <36...@users.noreply.github.com>
AuthorDate: Thu Feb 25 23:15:08 2021 +0800
feat(be): Online debug function adds support for transfer files (#1465)
---
.../route_online_debug/route_online_debug.go | 77 +-
api/test/e2e/route_online_debug_test.go | 849 ---------------------
api/test/e2enew/base/http.go | 53 ++
.../route_online_debug_suite_test.go | 37 +
.../route_online_debug/route_online_debug_test.go | 822 ++++++++++++++++++++
5 files changed, 961 insertions(+), 877 deletions(-)
diff --git a/api/internal/handler/route_online_debug/route_online_debug.go b/api/internal/handler/route_online_debug/route_online_debug.go
index ac1c502..3f8da4a 100644
--- a/api/internal/handler/route_online_debug/route_online_debug.go
+++ b/api/internal/handler/route_online_debug/route_online_debug.go
@@ -17,6 +17,7 @@
package route_online_debug
import (
+ "bytes"
"encoding/json"
"fmt"
"io/ioutil"
@@ -25,12 +26,13 @@ import (
"strings"
"time"
- "github.com/apisix/manager-api/internal/handler"
"github.com/gin-gonic/gin"
"github.com/shiningrush/droplet"
"github.com/shiningrush/droplet/data"
"github.com/shiningrush/droplet/wrapper"
wgin "github.com/shiningrush/droplet/wrapper/gin"
+
+ "github.com/apisix/manager-api/internal/handler"
)
type Handler struct {
@@ -45,16 +47,17 @@ type ProtocolSupport interface {
}
func (h *Handler) ApplyRoute(r *gin.Engine) {
- r.POST("/apisix/admin/debug-request-forwarding", wgin.Wraps(DebugRequestForwarding,
- wrapper.InputType(reflect.TypeOf(ParamsInput{}))))
+ r.POST("/apisix/admin/debug-request-forwarding", wgin.Wraps(h.DebugRequestForwarding,
+ wrapper.InputType(reflect.TypeOf(DebugOnlineInput{}))))
}
-type ParamsInput struct {
- URL string `json:"url,omitempty"`
- RequestProtocol string `json:"request_protocol,omitempty"`
- BodyParams string `json:"body_params,omitempty"`
- Method string `json:"method,omitempty"`
- HeaderParams map[string][]string `json:"header_params,omitempty"`
+type DebugOnlineInput struct {
+ URL string `auto_read:"online_debug_url,header"`
+ RequestProtocol string `auto_read:"online_debug_request_protocol,header"`
+ Method string `auto_read:"online_debug_method,header"`
+ HeaderParams string `auto_read:"online_debug_header_params,header"`
+ ContentType string `auto_read:"Content-Type,header"`
+ Body []byte `auto_read:"@body"`
}
type Result struct {
@@ -63,66 +66,84 @@ type Result struct {
Data interface{} `json:"data,omitempty"`
}
-func DebugRequestForwarding(c droplet.Context) (interface{}, error) {
+func (h *Handler) DebugRequestForwarding(c droplet.Context) (interface{}, error) {
//TODO: other Protocols, e.g: grpc, websocket
- paramsInput := c.Input().(*ParamsInput)
- requestProtocol := paramsInput.RequestProtocol
- if requestProtocol == "" {
- requestProtocol = "http"
+ input := c.Input().(*DebugOnlineInput)
+ protocol := input.RequestProtocol
+ if protocol == "" {
+ protocol = "http"
}
protocolMap := make(map[string]ProtocolSupport)
protocolMap["http"] = &HTTPProtocolSupport{}
protocolMap["https"] = &HTTPProtocolSupport{}
- if v, ok := protocolMap[requestProtocol]; ok {
- return v.RequestForwarding(c)
- } else {
- return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
- fmt.Errorf("Protocol unsupported %s, only http or https is allowed, but given %s", paramsInput.RequestProtocol, paramsInput.RequestProtocol)
+ if v, ok := protocolMap[protocol]; ok {
+ ret, err := v.RequestForwarding(c)
+ return ret, err
}
+
+ return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, fmt.Errorf("protocol unspported %s", protocol)
}
type HTTPProtocolSupport struct {
}
func (h *HTTPProtocolSupport) RequestForwarding(c droplet.Context) (interface{}, error) {
- paramsInput := c.Input().(*ParamsInput)
- bodyParams := paramsInput.BodyParams
- client := &http.Client{}
+ input := c.Input().(*DebugOnlineInput)
+ url := input.URL
+ method := input.Method
+ body := input.Body
+ contentType := input.ContentType
+
+ if url == "" || method == "" {
+ return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, fmt.Errorf("parameters error")
+ }
+ client := &http.Client{}
client.Timeout = 5 * time.Second
- req, err := http.NewRequest(strings.ToUpper(paramsInput.Method), paramsInput.URL, strings.NewReader(bodyParams))
+
+ var tempMap map[string][]string
+ err := json.Unmarshal([]byte(input.HeaderParams), &tempMap)
+
+ if err != nil {
+ return &data.SpecCodeResponse{StatusCode: http.StatusInternalServerError}, err
+ }
+
+ req, err := http.NewRequest(strings.ToUpper(method), url, bytes.NewReader(body))
if err != nil {
return &data.SpecCodeResponse{StatusCode: http.StatusInternalServerError}, err
}
- for k, v := range paramsInput.HeaderParams {
+
+ req.Header.Add("Content-Type", contentType)
+ for k, v := range tempMap {
for _, v1 := range v {
req.Header.Add(k, v1)
}
}
+
resp, err := client.Do(req)
if err != nil {
return &data.SpecCodeResponse{StatusCode: http.StatusInternalServerError}, err
}
+
defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
+ _body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return &data.SpecCodeResponse{StatusCode: http.StatusInternalServerError}, err
}
returnData := make(map[string]interface{})
result := &Result{}
- err = json.Unmarshal(body, &returnData)
+ err = json.Unmarshal(_body, &returnData)
if err != nil {
result.Code = resp.StatusCode
result.Message = resp.Status
- result.Data = string(body)
+ result.Data = string(_body)
} else {
result.Code = resp.StatusCode
result.Message = resp.Status
result.Data = returnData
-
}
return result, nil
}
diff --git a/api/test/e2e/route_online_debug_test.go b/api/test/e2e/route_online_debug_test.go
deleted file mode 100644
index 4665309..0000000
--- a/api/test/e2e/route_online_debug_test.go
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package e2e
-
-import (
- "io/ioutil"
- "net/http"
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/tidwall/gjson"
-)
-
-func TestRoute_Online_Debug_Route_Not_Exist(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "hit route that not exist",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello_",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
- },
- }
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
- basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding"
- request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello_","method": "GET","request_protocol": "http"}`))
- request.Header.Add("Authorization", token)
- resp, err := http.DefaultClient.Do(request)
- if err != nil {
- return
- }
- defer resp.Body.Close()
- respBody, _ := ioutil.ReadAll(resp.Body)
- realBody := gjson.Get(string(respBody), "data")
- assert.Equal(t, `{"code":404,"message":"404 Not Found","data":{"error_msg":"404 Route Not Found"}}`, realBody.String())
-}
-
-func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "hit route that not exist",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
- Sleep: sleepTime,
- },
- {
- Desc: "create route with query params",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "vars": [
- ["arg_name","==","aaa"]
- ],
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "online debug route with query params",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello?name=aaa",
- "request_protocol": "http",
- "method": "GET"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "create route with header params",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "vars": [
- ["http_version","==","v2"]
- ],
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "online debug route with header params",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello",
- "request_protocol": "http",
- "method": "GET",
- "header_params": {
- "version": ["v2"]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "create route with method POST",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["POST"],
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "online debug route with body params",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello",
- "request_protocol": "http",
- "method": "POST",
- "body_params": "{\"name\":\"test\",\"desc\":\"online debug route with body params\"}"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "create route enable basic-auth plugin",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "plugins": {
- "basic-auth": {}
- },
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "make sure the consumer is not created",
- Object: ManagerApiExpect(t),
- Method: http.MethodGet,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusNotFound,
- },
- {
- Desc: "create consumer",
- Object: ManagerApiExpect(t),
- Path: "/apisix/admin/consumers",
- Method: http.MethodPut,
- Body: `{
- "username": "jack",
- "plugins": {
- "basic-auth": {
- "disable": false,
- "username": "jack",
- "password": "123456"
- }
- },
- "desc": "test description"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "online debug route with username and password",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello",
- "request_protocol": "http",
- "method": "GET",
- "header_params": {
- "Authorization": ["Basic amFjazoxMjM0NTYKIA=="]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-
- // online debug without basic-auth
- basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding"
- request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello","method": "GET","request_protocol":"http"}`))
- request.Header.Add("Authorization", token)
- resp, err := http.DefaultClient.Do(request)
- if err != nil {
- return
- }
- defer resp.Body.Close()
- respBody, _ := ioutil.ReadAll(resp.Body)
- realBody := gjson.Get(string(respBody), "data")
- assert.Equal(t, `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing authorization in request"}}`, realBody.String())
-
- // clear test data
- tests = []HttpTestCase{
- {
- Desc: "delete consumer",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify route with the jwt token from just deleted consumer",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- Headers: map[string]string{"Authorization": "Basic amFjazoxMjM0NTYKIA=="},
- ExpectStatus: http.StatusUnauthorized,
- ExpectBody: `{"message":"Missing related consumer"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "create route enable jwt-auth plugin",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "plugins": {
- "jwt-auth": {}
- },
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- Sleep: sleepTime,
- },
- {
- Desc: "make sure the consumer is not created",
- Object: ManagerApiExpect(t),
- Method: http.MethodGet,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusNotFound,
- Sleep: sleepTime,
- },
- {
- Desc: "create consumer",
- Object: ManagerApiExpect(t),
- Path: "/apisix/admin/consumers",
- Method: http.MethodPut,
- Body: `{
- "username": "jack",
- "plugins": {
- "jwt-auth": {
- "key": "user-key",
- "secret": "my-secret-key",
- "algorithm": "HS256"
- }
- },
- "desc": "test description"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-
- time.Sleep(sleepTime)
-
- // sign jwt token
- body, status, err := httpGet("http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key", nil)
- assert.Nil(t, err)
- assert.Equal(t, http.StatusOK, status)
- jwtToken := string(body)
-
- tests = []HttpTestCase{
- {
- Desc: "online debug route with jwt token",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello",
- "request_protocol": "http",
- "method": "GET",
- "header_params": {
- "Authorization": ["` + jwtToken + `"]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-
- // online debug without jwt-auth
- basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding"
- request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello","method": "GET","request_protocol":"http"}`))
- request.Header.Add("Authorization", token)
- resp, err := http.DefaultClient.Do(request)
- if err != nil {
- return
- }
- defer resp.Body.Close()
- respBody, _ := ioutil.ReadAll(resp.Body)
- realBody := gjson.Get(string(respBody), "data")
- assert.Equal(t, `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing JWT token in request"}}`, realBody.String())
-
- // clear test data
- tests = []HttpTestCase{
- {
- Desc: "delete consumer",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify route with the jwt token from just deleted consumer",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- Headers: map[string]string{"Authorization": jwtToken},
- ExpectStatus: http.StatusUnauthorized,
- ExpectBody: `{"message":"Missing related consumer"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- },
- {
- Desc: "create route enable key-auth plugin",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "plugins": {
- "key-auth": {}
- },
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "make sure the consumer is not created",
- Object: ManagerApiExpect(t),
- Method: http.MethodGet,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusNotFound,
- },
- {
- Desc: "create consumer",
- Object: ManagerApiExpect(t),
- Path: "/apisix/admin/consumers",
- Method: http.MethodPut,
- Body: `{
- "username": "jack",
- "plugins": {
- "key-auth": {
- "key": "user-key"
- }
- },
- "desc": "test description"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "online debug route with apikey",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello",
- "request_protocol": "http",
- "method": "GET",
- "header_params": {
- "apikey": ["user-key"]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-
- // online debug without key-auth
- basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding"
- request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello","method": "GET","request_protocol": "http"}`))
- request.Header.Add("Authorization", token)
- resp, err := http.DefaultClient.Do(request)
- if err != nil {
- return
- }
- defer resp.Body.Close()
- respBody, _ := ioutil.ReadAll(resp.Body)
- realBody := gjson.Get(string(respBody), "data")
- assert.Equal(t, `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing API key found in request"}}`, realBody.String())
-
- // clear test data
- tests = []HttpTestCase{
- {
- Desc: "delete consumer",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify route with the jwt token from just deleted consumer",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- Headers: map[string]string{"apikey": "user-key"},
- ExpectStatus: http.StatusUnauthorized,
- ExpectBody: `{"message":"Missing related consumer"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
-
-func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) {
- tests := []HttpTestCase{
- {
- Desc: "make sure the route is not created ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- },
- {
- Desc: "create route enable key-auth plugin",
- Object: ManagerApiExpect(t),
- Method: http.MethodPut,
- Path: "/apisix/admin/routes/r1",
- Body: `{
- "uri": "/hello",
- "methods": ["GET"],
- "vars": [
- ["arg_name","==","aaa"]
- ],
- "plugins": {
- "key-auth": {}
- },
- "upstream": {
- "type": "roundrobin",
- "nodes": [{
- "host": "172.16.238.20",
- "port": 1980,
- "weight": 1
- }]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "make sure the consumer is not created",
- Object: ManagerApiExpect(t),
- Method: http.MethodGet,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusNotFound,
- },
- {
- Desc: "create consumer",
- Object: ManagerApiExpect(t),
- Path: "/apisix/admin/consumers",
- Method: http.MethodPut,
- Body: `{
- "username": "jack",
- "plugins": {
- "key-auth": {
- "key": "user-key"
- }
- },
- "desc": "test description"
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "online debug route with apikey",
- Object: ManagerApiExpect(t),
- Method: http.MethodPost,
- Path: "/apisix/admin/debug-request-forwarding",
- Body: `{
- "url": "` + APISIXInternalUrl + `/hello?name=aaa",
- "request_protocol": "http",
- "method": "GET",
- "header_params": {
- "apikey": ["user-key"]
- }
- }`,
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-
- // online debug without key-auth
- basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding"
- request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello?name=aaa","method": "GET","request_protocol": "http"}`))
- request.Header.Add("Authorization", token)
- resp, err := http.DefaultClient.Do(request)
- if err != nil {
- return
- }
- defer resp.Body.Close()
- respBody, _ := ioutil.ReadAll(resp.Body)
- realBody := gjson.Get(string(respBody), "data")
- assert.Equal(t, `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing API key found in request"}}`, realBody.String())
-
- // clear test data
- tests = []HttpTestCase{
- {
- Desc: "delete consumer",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/consumers/jack",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify route with the jwt token from just deleted consumer",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: `/hello`,
- Query: "name=aaa",
- Headers: map[string]string{"apikey": "user-key"},
- ExpectStatus: http.StatusUnauthorized,
- ExpectBody: `{"message":"Missing related consumer"}`,
- Sleep: sleepTime,
- },
- {
- Desc: "delete route",
- Object: ManagerApiExpect(t),
- Method: http.MethodDelete,
- Path: "/apisix/admin/routes/r1",
- Headers: map[string]string{"Authorization": token},
- ExpectStatus: http.StatusOK,
- },
- {
- Desc: "verify the deleted route ",
- Object: APISIXExpect(t),
- Method: http.MethodGet,
- Path: "/hello",
- ExpectStatus: http.StatusNotFound,
- ExpectBody: `{"error_msg":"404 Route Not Found"}`,
- Sleep: sleepTime,
- },
- }
-
- for _, tc := range tests {
- testCaseCheck(tc, t)
- }
-}
diff --git a/api/test/e2enew/base/http.go b/api/test/e2enew/base/http.go
index 1ca2433..fda1593 100644
--- a/api/test/e2enew/base/http.go
+++ b/api/test/e2enew/base/http.go
@@ -18,12 +18,24 @@ package base
import (
"bytes"
+ "encoding/json"
+ "io"
"io/ioutil"
+ "mime/multipart"
"net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
"github.com/stretchr/testify/assert"
)
+type UploadFile struct {
+ Name string
+ Filepath string
+}
+
func HttpGet(url string, headers map[string]string) ([]byte, int, error) {
return httpRequest(http.MethodGet, url, headers, "")
}
@@ -92,3 +104,44 @@ func BatchTestServerPort(times int) map[string]int {
return res
}
+
+func GetReader(reqParams map[string]string, contentType string, files []UploadFile) (io.Reader, string, error) {
+ if strings.Index(contentType, "json") > -1 {
+ bytesData, _ := json.Marshal(reqParams)
+ return bytes.NewReader(bytesData), contentType, nil
+ }
+ if files != nil {
+ body := &bytes.Buffer{}
+ writer := multipart.NewWriter(body)
+ for _, uploadFile := range files {
+ file, err := os.Open(uploadFile.Filepath)
+ if err != nil {
+ return nil, "", err
+ }
+ defer file.Close()
+ part, err := writer.CreateFormFile(uploadFile.Name, filepath.Base(uploadFile.Filepath))
+ if err != nil {
+ return nil, "", err
+ }
+ _, err = io.Copy(part, file)
+ }
+ for k, v := range reqParams {
+ if err := writer.WriteField(k, v); err != nil {
+ return nil, "", err
+ }
+ }
+ if err := writer.Close(); err != nil {
+ return nil, "", err
+ }
+ return body, writer.FormDataContentType(), nil
+ }
+
+ urlValues := url.Values{}
+ for key, val := range reqParams {
+ urlValues.Set(key, val)
+ }
+
+ reqBody := urlValues.Encode()
+
+ return strings.NewReader(reqBody), contentType, nil
+}
diff --git a/api/test/e2enew/route_online_debug/route_online_debug_suite_test.go b/api/test/e2enew/route_online_debug/route_online_debug_suite_test.go
new file mode 100644
index 0000000..d92a29e
--- /dev/null
+++ b/api/test/e2enew/route_online_debug/route_online_debug_suite_test.go
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package route_online_debug
+
+import (
+ "testing"
+ "time"
+
+ "github.com/onsi/ginkgo"
+
+ "e2enew/base"
+)
+
+func TestRoute(t *testing.T) {
+ ginkgo.RunSpecs(t, "route online debug suite")
+}
+
+var _ = ginkgo.AfterSuite(func() {
+ base.CleanResource("routes")
+ base.CleanResource("consumers")
+ time.Sleep(base.SleepTime)
+})
+
diff --git a/api/test/e2enew/route_online_debug/route_online_debug_test.go b/api/test/e2enew/route_online_debug/route_online_debug_test.go
new file mode 100644
index 0000000..0b6b935
--- /dev/null
+++ b/api/test/e2enew/route_online_debug/route_online_debug_test.go
@@ -0,0 +1,822 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package route_online_debug
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "path/filepath"
+
+ "github.com/onsi/ginkgo"
+ "github.com/onsi/ginkgo/extensions/table"
+ "github.com/stretchr/testify/assert"
+ "github.com/tidwall/gjson"
+
+ "e2enew/base"
+)
+
+var upstream map[string]interface{} = map[string]interface{}{
+ "type": "roundrobin",
+ "nodes": []map[string]interface{}{
+ {
+ "host": base.UpstreamIp,
+ "port": 1980,
+ "weight": 1,
+ },
+ },
+}
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_Not_Exist", func() {
+ table.DescribeTable("Route_Online_Debug_Route_Not_Exist",
+ func(tc base.HttpTestCase) {
+ base.RunTestCase(tc)
+ },
+ table.Entry("hit route that not exist", base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello_",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ }),
+ table.Entry("online debug route with query params", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello_`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `{"code":404,"message":"404 Not Found","data":{"error_msg":"404 Route Not Found"}}`,
+ Sleep: base.SleepTime,
+ }),
+ )
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Query_Params", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route with query params", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "methods": []string{"GET"},
+ "vars": []interface{}{
+ []string{"arg_name", "==", "aaa"},
+ },
+ "upstream": upstream,
+ }
+ _routeBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_routeBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("online debug route with query params", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello?name=aaa`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Header_Params", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route with header params", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "methods": []string{"GET"},
+ "vars": []interface{}{
+ []string{"http_version", "==", "v2"},
+ },
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("online debug route with header params", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"],"version":["v2"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Body_Params", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route with method POST", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "methods": []string{"POST"},
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("online debug route with body params", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Body: `{
+ "name": "test",
+ "desc": "online debug route with body params"
+ }`,
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": http.MethodPost,
+ "Content-Type": "application/json",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+})
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Basic_Auth", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route enable basic-auth plugin", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "plugins": map[string]interface{}{
+ "basic-auth": map[string]interface{}{},
+ },
+ "methods": []string{"GET"},
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("make sure the consumer is not created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusNotFound,
+ })
+ })
+ ginkgo.It("create consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/consumers",
+ Body: `{
+ "username": "jack",
+ "plugins": {
+ "basic-auth": {
+ "disable": false,
+ "username": "jack",
+ "password": "123456"
+ }
+ },
+ "desc": "test description"
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("online debug with basic-auth", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"],"Authorization": ["Basic amFjazoxMjM0NTYKIA=="]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ })
+ })
+ ginkgo.It("online debug without basic-auth", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing authorization in request"}}`,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Key_Auth", func() {
+
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route enable key-auth plugin", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "plugins": map[string]interface{}{
+ "key-auth": map[string]interface{}{},
+ },
+ "methods": []string{"GET"},
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("make sure the consumer is not created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusNotFound,
+ })
+ })
+ ginkgo.It("create consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/consumers",
+ Body: `{
+ "username": "jack",
+ "plugins": {
+ "key-auth": {
+ "key": "user-key"
+ }
+ },
+ "desc": "test description"
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("online debug with key-auth", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"],"apikey":["user-key"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ })
+ })
+ ginkgo.It("online debug without key-auth", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":401,"message":"401 Unauthorized","data":{"message":"Missing API key found in request"}}`,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_JWT_Auth", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route enable jwt-auth plugin", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello",
+ "plugins": map[string]interface{}{
+ "jwt-auth": map[string]interface{}{},
+ },
+ "methods": []string{"GET"},
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r1",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("make sure the consumer is not created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusNotFound,
+ })
+ })
+ ginkgo.It("create consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/consumers",
+ Body: `{
+ "username": "jack",
+ "plugins": {
+ "jwt-auth": {
+ "key": "user-key",
+ "secret": "my-secret-key",
+ "algorithm": "HS256"
+ }
+ },
+ "desc": "test description"
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("online debug with JWT-auth", func() {
+ t := ginkgo.GinkgoT()
+ jsonStr := `{"test":["test1"]}`
+ var _headerParams map[string]interface{}
+ err := json.Unmarshal([]byte(jsonStr), &_headerParams)
+ assert.Nil(t, err)
+ jwtToken := base.GetJwtToken("user-key")
+ l := []string{jwtToken}
+ _headerParams["Authorization"] = l
+ headerParams, err := json.Marshal(_headerParams)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": string(headerParams),
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":200,"message":"200 OK","data":"hello world`,
+ })
+ })
+ ginkgo.It("online debug without JWT-auth", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/debug-request-forwarding",
+ Headers: map[string]string{
+ "Authorization": base.GetToken(),
+ "online_debug_url": base.APISIXInternalUrl + `/hello`,
+ "online_debug_request_protocol": "http",
+ "online_debug_method": "GET",
+ "Content-Type": "multipart/form-data",
+ "online_debug_header_params": `{"test":["test1"]}`,
+ },
+ ExpectStatus: http.StatusOK,
+ ExpectBody: `"data":{"code":401,"message":"401 Unauthorized","data":{"message":"Missing JWT token in request"}}`,
+ })
+ })
+ ginkgo.It("delete the route just created", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/r1",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("delete consumer", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/consumers/jack",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ })
+ })
+})
+
+var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Files", func() {
+ ginkgo.It("hit route that not exist", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ })
+ })
+ ginkgo.It("create route enable basic-auth plugin", func() {
+ t := ginkgo.GinkgoT()
+ var routeBody map[string]interface{} = map[string]interface{}{
+ "uri": "/hello_",
+ "methods": []string{"POST"},
+ "upstream": upstream,
+ }
+ _reqRouteBody, err := json.Marshal(routeBody)
+ assert.Nil(t, err)
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/routes/r2",
+ Body: string(_reqRouteBody),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ })
+ })
+ ginkgo.It("online debug with file", func() {
+ t := ginkgo.GinkgoT()
+ path, err := filepath.Abs("../../testdata/import/default.yaml")
+ assert.Nil(t, err)
+ files := []base.UploadFile{
+ {Name: "file", Filepath: path},
+ }
+
+ headers := map[string]string{}
+
+ jsonStr := `{"test":["test1"]}`
+ var _headerParams map[string]interface{}
+ err = json.Unmarshal([]byte(jsonStr), &_headerParams)
+ assert.Nil(t, err)
+ l := []string{base.GetToken()}
+ _headerParams["Authorization"] = l
+ headerParams, err := json.Marshal(_headerParams)
+ assert.Nil(t, err)
+
+ basePath := base.ManagerAPIHost + "/apisix/admin/debug-request-forwarding"
+ requestBody, requestContentType, err := base.GetReader(headers, "multipart/form-data", files)
+ assert.Nil(t, err)
+ httpRequest, err := http.NewRequest(http.MethodPost, basePath, requestBody)
+ assert.Nil(t, err)
+ httpRequest.Header.Add("Content-Type", requestContentType)
+ httpRequest.Header.Add("Authorization", base.GetToken())
+ httpRequest.Header.Add("online_debug_request_protocol", "http")
+ httpRequest.Header.Add("online_debug_url", base.ManagerAPIHost+`/apisix/admin/import/routes`)
+ httpRequest.Header.Add("online_debug_method", http.MethodPost)
+ httpRequest.Header.Add("online_debug_header_params", string(headerParams))
+ client := &http.Client{}
+ resp, err := client.Do(httpRequest)
+ assert.Nil(t, err)
+
+ defer resp.Body.Close()
+
+ respBody, err := ioutil.ReadAll(resp.Body)
+ assert.Nil(t, err)
+ realBody := gjson.Get(string(respBody), "data")
+ // todo get successful result and compare
+ assert.Contains(t, realBody.String(), `"data":{"paths":1,"routes":1}`)
+ })
+
+ ginkgo.It("verify the route just imported and delete data", func() {
+ t := ginkgo.GinkgoT()
+ request, _ := http.NewRequest("GET", base.ManagerAPIHost+"/apisix/admin/routes", nil)
+ request.Header.Add("Authorization", base.GetToken())
+ resp, err := http.DefaultClient.Do(request)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ respBody, _ := ioutil.ReadAll(resp.Body)
+ list := gjson.Get(string(respBody), "data.rows").Value().([]interface{})
+
+ var tests []base.HttpTestCase
+ for _, item := range list {
+ route := item.(map[string]interface{})
+ tc := base.HttpTestCase{
+ Desc: "route patch for update status(online)",
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPatch,
+ Path: "/apisix/admin/routes/" + route["id"].(string),
+ Body: `{"status":1}`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ Sleep: base.SleepTime,
+ }
+ tests = append(tests, tc)
+ }
+
+ // verify route
+ tests = append(tests, base.HttpTestCase{
+ Desc: "verify the route just imported",
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusOK,
+ ExpectBody: "hello world",
+ Sleep: base.SleepTime,
+ })
+
+ // delete test data
+ for _, item := range list {
+ route := item.(map[string]interface{})
+ tc := base.HttpTestCase{
+ Desc: "delete route",
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/routes/" + route["id"].(string),
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ }
+ tests = append(tests, tc)
+ }
+
+ for _, tc := range tests {
+ base.RunTestCase(tc)
+ }
+
+ })
+
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+
+ ginkgo.It("hit the route just deleted", func() {
+ base.RunTestCase(base.HttpTestCase{
+ Object: base.APISIXExpect(),
+ Method: http.MethodGet,
+ Path: "/hello_",
+ ExpectStatus: http.StatusNotFound,
+ ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
+ Sleep: base.SleepTime,
+ })
+ })
+})