You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by li...@apache.org on 2021/04/09 01:43:14 UTC

[apisix-dashboard] branch master updated: feat: add response header in debug view (#1691)

This is an automated email from the ASF dual-hosted git repository.

liuxiran 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 79fd15a  feat: add response header in debug view (#1691)
79fd15a is described below

commit 79fd15a2d6355401f735cbaa5cbe512f2c8a15dc
Author: Cliff Su <st...@yahoo.com.tw>
AuthorDate: Fri Apr 9 09:43:03 2021 +0800

    feat: add response header in debug view (#1691)
    
    * feat: add response header in debug view
    
    Co-authored-by: 琚致远 <ju...@apache.org>
---
 .../route_online_debug/route_online_debug.go       |  3 +++
 .../route_online_debug/route_online_debug_test.go  | 22 ++++++++---------
 .../Route/components/DebugViews/DebugDrawView.tsx  | 28 ++++++++++++++++++----
 web/src/pages/Route/locales/en-US.ts               |  1 +
 web/src/pages/Route/locales/zh-CN.ts               |  1 +
 5 files changed, 40 insertions(+), 15 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 e7bbee3..b7886a9 100644
--- a/api/internal/handler/route_online_debug/route_online_debug.go
+++ b/api/internal/handler/route_online_debug/route_online_debug.go
@@ -62,6 +62,7 @@ type DebugOnlineInput struct {
 
 type Result struct {
 	Code    int         `json:"code,omitempty"`
+	Header  interface{} `json:"header,omitempty"`
 	Message string      `json:"message,omitempty"`
 	Data    interface{} `json:"data,omitempty"`
 }
@@ -142,10 +143,12 @@ func (h *HTTPProtocolSupport) RequestForwarding(c droplet.Context) (interface{},
 	err = json.Unmarshal(_body, &returnData)
 	if err != nil {
 		result.Code = resp.StatusCode
+		result.Header = resp.Header
 		result.Message = resp.Status
 		result.Data = string(_body)
 	} else {
 		result.Code = resp.StatusCode
+		result.Header = resp.Header
 		result.Message = resp.Status
 		result.Data = returnData
 	}
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
index 166862f..c32e59a 100644
--- a/api/test/e2enew/route_online_debug/route_online_debug_test.go
+++ b/api/test/e2enew/route_online_debug/route_online_debug_test.go
@@ -67,7 +67,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_Not_Exist", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `{"code":404,"message":"404 Not Found","data":{"error_msg":"404 Route Not Found"}}`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":404,"header":{"Connection":["keep-alive"],"Content-Type":["text/plain; charset=utf-8"]`,
 			Sleep:        base.SleepTime,
 		}),
 	)
@@ -118,7 +118,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Query_Params", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"],`,
 			Sleep:        base.SleepTime,
 		})
 	})
@@ -189,7 +189,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Header_Params", func() {
 				"online_debug_header_params":    `{"test":["test1"],"version":["v2"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"],`,
 			Sleep:        base.SleepTime,
 		})
 	})
@@ -217,7 +217,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Header_Params", func() {
 				"online_debug_header_params":    `{"Content-type":["application/json"],"Authorization":["` + base.GetToken() + `"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `{"code":200,"message":"200 OK"`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization"],"Access-Control-Allow-Methods":["*"],"Access-Control-Allow-Origin":["*"],"Content-Length":["296"],"Content-Type":["application/json"]`,
 			Sleep:        base.SleepTime,
 		})
 	})
@@ -318,7 +318,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Body_Params", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"]`,
 			Sleep:        base.SleepTime,
 		})
 	})
@@ -418,7 +418,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Basic_Auth", func() {
 				"online_debug_header_params":    `{"test":["test1"],"Authorization": ["Basic amFjazoxMjM0NTYKIA=="]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"]`,
 		})
 	})
 	ginkgo.It("online debug without basic-auth", func() {
@@ -435,7 +435,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Basic_Auth", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `{"code":401,"message":"401 Unauthorized","data":{"message":"Missing authorization in request"}}`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":401,"header":{"Connection":["keep-alive"],"Content-Type":["text/plain; charset=utf-8"],`,
 		})
 	})
 	ginkgo.It("delete the route just created", func() {
@@ -542,7 +542,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Key_Auth", func() {
 				"online_debug_header_params":    `{"test":["test1"],"apikey":["user-key"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"],`,
 		})
 	})
 	ginkgo.It("online debug without key-auth", func() {
@@ -559,7 +559,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_Key_Auth", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":401,"message":"401 Unauthorized","data":{"message":"Missing API key found in request"}}`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":401,"header":{"Connection":["keep-alive"],"Content-Type":["text/plain; charset=utf-8"]`,
 		})
 	})
 	ginkgo.It("delete the route just created", func() {
@@ -676,7 +676,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_JWT_Auth", func() {
 				"online_debug_header_params":    string(headerParams),
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":200,"message":"200 OK","data":"hello world`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":200,"header":{"Connection":["keep-alive"],"Content-Type":["application/octet-stream"],`,
 		})
 	})
 	ginkgo.It("online debug without JWT-auth", func() {
@@ -693,7 +693,7 @@ var _ = ginkgo.Describe("Route_Online_Debug_Route_With_JWT_Auth", func() {
 				"online_debug_header_params":    `{"test":["test1"]}`,
 			},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"data":{"code":401,"message":"401 Unauthorized","data":{"message":"Missing JWT token in request"}}`,
+			ExpectBody:   `{"code":0,"message":"","data":{"code":401,"header":{"Connection":["keep-alive"],"Content-Type":["text/plain; charset=utf-8"],`,
 		})
 	})
 	ginkgo.It("delete the route just created", func() {
diff --git a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
index da4d2d3..09300b6 100644
--- a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
+++ b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
@@ -50,7 +50,8 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
   const [formDataForm] = Form.useForm();
   const [authForm] = Form.useForm();
   const [headerForm] = Form.useForm();
-  const [responseCode, setResponseCode] = useState<string>();
+  const [responseBody, setResponseBody] = useState<string>();
+  const [responseHeader, setResponseHeader] = useState<string>();
   const [loading, setLoading] = useState(false);
   const [codeMirrorHeight, setCodeMirrorHeight] = useState<number | string>(50);
   const bodyCodeMirrorRef = useRef<any>(null);
@@ -73,7 +74,8 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
     formDataForm.setFieldsValue(DEFAULT_DEBUG_PARAM_FORM_DATA);
     headerForm.setFieldsValue(DEFAULT_DEBUG_PARAM_FORM_DATA);
     authForm.setFieldsValue(DEFAULT_DEBUG_AUTH_FORM_DATA);
-    setResponseCode(`${formatMessage({ id: 'page.route.debug.showResultAfterSendRequest' })}`);
+    setResponseBody(formatMessage({ id: 'page.route.debug.showResultAfterSendRequest' }));
+    setResponseHeader(formatMessage({ id: 'page.route.debug.showResultAfterSendRequest' }));
     setBodyType(DEBUG_BODY_TYPE_SUPPORTED[DebugBodyType.None]);
   };
 
@@ -227,7 +229,8 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
     }, bodyFormData)
       .then((req) => {
         setLoading(false);
-        setResponseCode(JSON.stringify(req.data.data, null, 2));
+        setResponseBody(JSON.stringify(req.data.data, null, 2));
+        setResponseHeader(JSON.stringify(req.data.header, null, 2));
         setCodeMirrorHeight('auto');
       })
       .catch(() => {
@@ -391,7 +394,7 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
               <Spin tip="Loading..." spinning={loading}>
                 <div id='codeMirror-response'>
                   <CodeMirror
-                    value={responseCode}
+                    value={responseBody}
                     height={codeMirrorHeight}
                     options={{
                       mode: 'json-ld',
@@ -406,6 +409,23 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
                 </div>
               </Spin>
             </TabPane>
+            <TabPane tab={formatMessage({ id: 'page.route.TabPane.header' })} key="header">
+              <Spin tip="Loading..." spinning={loading}>
+                <CodeMirror
+                  value={responseHeader}
+                  height={codeMirrorHeight}
+                  options={{
+                    mode: 'json-ld',
+                    readOnly: 'nocursor',
+                    lineWrapping: true,
+                    lineNumbers: true,
+                    showCursorWhenSelecting: true,
+                    autofocus: true,
+                    scrollbarStyle: null,
+                  }}
+                />
+              </Spin>
+            </TabPane>
           </Tabs>
         </PanelSection>
       </Card>
diff --git a/web/src/pages/Route/locales/en-US.ts b/web/src/pages/Route/locales/en-US.ts
index 9ac5d2b..7e52826 100644
--- a/web/src/pages/Route/locales/en-US.ts
+++ b/web/src/pages/Route/locales/en-US.ts
@@ -135,6 +135,7 @@ export default {
   'page.route.TabPane.headerParams': 'Header Params',
   'page.route.TabPane.authentication': 'Authentication',
   'page.route.TabPane.response': 'Response',
+  'page.route.TabPane.header': 'Response Header',
   'page.route.debugWithoutAuth': 'This request does not use any authorization.',
   'page.route.button.exportOpenApi': 'Export OpenAPI',
   'page.route.exportRoutesTips': 'Please choose the type of file you want to export',
diff --git a/web/src/pages/Route/locales/zh-CN.ts b/web/src/pages/Route/locales/zh-CN.ts
index f2a0d28..7e7f635 100644
--- a/web/src/pages/Route/locales/zh-CN.ts
+++ b/web/src/pages/Route/locales/zh-CN.ts
@@ -136,6 +136,7 @@ export default {
   'page.route.TabPane.headerParams': '请求头参数',
   'page.route.TabPane.authentication': '认证',
   'page.route.TabPane.response': '响应结果',
+  'page.route.TabPane.header': '响应请求头参数',
   'page.route.debugWithoutAuth': '当前请求不启用任何认证方式。',
   'page.route.button.exportOpenApi': '导出 OpenAPI',
   'page.route.exportRoutesTips': '请选择导出文件的类型',