Skip to content

Commit 6eb2483

Browse files
committed
feat: handle big response
1 parent e14ab75 commit 6eb2483

File tree

8 files changed

+816
-689
lines changed

8 files changed

+816
-689
lines changed

console/atest-ui/src/views/TestCase.vue

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,11 @@ const handleTestResult = (e) => {
9898
if (!isHistoryTestCase.value) {
9999
handleTestResultError(e)
100100
}
101+
const isFilePath = e.body.startsWith("isFilePath-")
101102
102-
if (e.body !== '') {
103+
if(isFilePath){
104+
isResponseFile.value = true
105+
} else if(e.body !== ''){
103106
testResult.value.bodyObject = JSON.parse(e.body);
104107
testResult.value.originBodyObject = JSON.parse(e.body);
105108
}
@@ -312,6 +315,33 @@ function determineBodyType(e) {
312315
});
313316
}
314317
318+
const isResponseFile = ref(false)
319+
function downloadResponseFile(){
320+
API.DownloadResponseFile({
321+
body: testResult.value.body
322+
}, (e) => {
323+
if (e && e.data) {
324+
try {
325+
const bytes = atob(e.data);
326+
const blob = new Blob([bytes], { type: 'mimeType' });
327+
const link = document.createElement('a');
328+
link.href = window.URL.createObjectURL(blob);
329+
link.download = e.filename.substring("isFilePath-".length);
330+
331+
document.body.appendChild(link);
332+
link.click();
333+
334+
window.URL.revokeObjectURL(link.href);
335+
document.body.removeChild(link);
336+
} catch (error) {
337+
console.error('Error during file download:', error);
338+
}
339+
} else {
340+
console.error('No data to download.');
341+
}
342+
})
343+
}
344+
315345
function setDefaultValues(e) {
316346
if (e.request.method === '') {
317347
e.request.method = 'GET'
@@ -1154,10 +1184,20 @@ Magic.Keys(() => {
11541184
<div v-if="testResult.bodyObject">
11551185
<el-input :prefix-icon="Search" @change="responseBodyFilter" v-model="responseBodyFilterText"
11561186
clearable placeholder="$.key" />
1157-
<JsonViewer :value="testResult.bodyObject" :expand-depth="2" copyable boxed sort />
1187+
<JsonViewer :value="testResult.bodyObject" :expand-depth="5" copyable boxed sort />
11581188
</div>
11591189
<div v-else>
1160-
<Codemirror v-model="testResult.bodyText"/>
1190+
<Codemirror v-if="!isResponseFile" v-model="testResult.bodyText"/>
1191+
<div v-if="isResponseFile" style="padding-top: 10px;">
1192+
<el-row>
1193+
<el-col :span="8">
1194+
<div>Response body is too large, please download to view.</div>
1195+
</el-col>
1196+
<el-col :span="4">
1197+
<el-button type="primary" @click="downloadResponseFile">Download</el-button>
1198+
</el-col>
1199+
</el-row>
1200+
</div>
11611201
</div>
11621202
</el-tab-pane>
11631203
<el-tab-pane name="response-header">

console/atest-ui/src/views/net.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,13 +655,32 @@ function GetTestCaseAllHistory(req: TestCase,
655655
.then(callback).catch(errHandle)
656656
}
657657

658+
function DownloadResponseFile(testcase,
659+
callback: (d: any) => void, errHandle?: (e: any) => void | null) {
660+
const requestOptions = {
661+
method: 'POST',
662+
headers: {
663+
'X-Store-Name': Cache.GetCurrentStore().name,
664+
'X-Auth': getToken()
665+
},
666+
body: JSON.stringify({
667+
response: {
668+
body: testcase.body,
669+
}
670+
})
671+
}
672+
fetch(`/api/v1/downloadFile/${testcase.body}`, requestOptions)
673+
.then(DefaultResponseProcess)
674+
.then(callback).catch(errHandle)
675+
}
676+
658677

659678
export const API = {
660679
DefaultResponseProcess,
661680
GetVersion,
662681
CreateTestSuite, UpdateTestSuite, ImportTestSuite, GetTestSuite, DeleteTestSuite, ConvertTestSuite,GetTestSuiteYaml,
663682
CreateTestCase, UpdateTestCase, GetTestCase, ListTestCase, DeleteTestCase, RunTestCase,
664-
GetHistoryTestCaseWithResult, DeleteHistoryTestCase,GetHistoryTestCase, RunHistoryTestCase, GetTestCaseAllHistory, DeleteAllHistoryTestCase,
683+
GetHistoryTestCaseWithResult, DeleteHistoryTestCase,GetHistoryTestCase, GetTestCaseAllHistory, DeleteAllHistoryTestCase, DownloadResponseFile,
665684
GenerateCode, ListCodeGenerator,
666685
PopularHeaders,
667686
CreateOrUpdateStore, GetStores, DeleteStore, VerifyStore,

pkg/server/remote_server.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ import (
2222
"errors"
2323
"fmt"
2424
"io"
25+
"mime"
2526
"net/http"
2627
"os"
28+
"path/filepath"
2729
reflect "reflect"
2830
"regexp"
2931
"strings"
@@ -252,6 +254,7 @@ func (s *server) Run(ctx context.Context, task *TestTask) (reply *TestResult, er
252254
output, testErr := suiteRunner.RunTestCase(&testCase, dataContext, ctx)
253255
if getter, ok := suiteRunner.(runner.ResponseRecord); ok {
254256
resp := getter.GetResponseRecord()
257+
resp, err = handleLargeResponseBody(resp, suite.Name, testCase.Name)
255258
reply.TestCaseResult = append(reply.TestCaseResult, &TestCaseResult{
256259
StatusCode: int32(resp.StatusCode),
257260
Body: resp.Body,
@@ -291,6 +294,65 @@ func (s *server) Run(ctx context.Context, task *TestTask) (reply *TestResult, er
291294
return
292295
}
293296

297+
func handleLargeResponseBody(resp runner.SimpleResponse, suite string, caseName string) (reply runner.SimpleResponse, err error) {
298+
const maxSize = 1024
299+
prefix := "isFilePath-" + strings.Join([]string{suite, caseName}, "-")
300+
301+
if len(resp.Body) > maxSize {
302+
tmpFile, err := os.CreateTemp("", prefix+"-")
303+
defer tmpFile.Close()
304+
if err != nil {
305+
return resp, fmt.Errorf("failed to create file: %w", err)
306+
}
307+
308+
if _, err = tmpFile.Write([]byte(resp.Body)); err != nil {
309+
return resp, fmt.Errorf("failed to write response body to file: %w", err)
310+
}
311+
absFilePath, err := filepath.Abs(tmpFile.Name())
312+
if err != nil {
313+
return resp, fmt.Errorf("failed to get absolute file path: %w", err)
314+
}
315+
resp.Body = filepath.Base(absFilePath)
316+
return resp, nil
317+
}
318+
return resp, nil
319+
}
320+
321+
func (s *server) DownloadResponseFile(ctx context.Context, in *TestCase) (reply *FileData, err error) {
322+
if in.Response != nil {
323+
tempFileName := in.Response.Body
324+
if tempFileName == "" {
325+
return nil, errors.New("file name is empty")
326+
}
327+
328+
tempDir := os.TempDir()
329+
filePath := filepath.Join(tempDir, tempFileName)
330+
if filepath.Clean(filePath) != filepath.Join(tempDir, filepath.Base(tempFileName)) {
331+
return nil, errors.New("invalid file path")
332+
}
333+
334+
fileContent, err := os.ReadFile(filePath)
335+
if err != nil {
336+
return nil, fmt.Errorf("failed to read file: %s", filePath)
337+
}
338+
339+
mimeType := mime.TypeByExtension(filepath.Ext(filePath))
340+
if mimeType == "" {
341+
mimeType = "application/octet-stream"
342+
}
343+
344+
reply = &FileData{
345+
Data: fileContent,
346+
ContentType: mimeType,
347+
Filename: filepath.Base(filePath),
348+
}
349+
350+
return reply, nil
351+
} else {
352+
return reply, errors.New("response is empty")
353+
}
354+
}
355+
294356
func (s *server) RunTestSuite(srv Runner_RunTestSuiteServer) (err error) {
295357
ctx := srv.Context()
296358
for {

0 commit comments

Comments
 (0)