Skip to content

Commit 217f9f4

Browse files
authored
Fix: #676 Handle text/plain response content type correctly (#677)
Fix: Handle text/plain response content type correctly
1 parent f989857 commit 217f9f4

File tree

2 files changed

+97
-11
lines changed

2 files changed

+97
-11
lines changed

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,17 @@ const parseResponseBody = (body: any) => {
112112
}
113113
}
114114
115-
const handleTestResult = (e: any) => {
115+
/**
116+
* Handles test result data from API response
117+
*
118+
* Processes the test response with proper error handling and content type detection:
119+
* - For JSON responses: Parses and makes it available for filtering/display
120+
* - For plain text responses: Displays as raw text without JSON parsing
121+
* - For file responses: Handles as downloadable content
122+
*
123+
* @param e The test result data from API
124+
*/
125+
const handleTestResult = (e: any): void => {
116126
testResult.value = e;
117127
118128
if (!isHistoryTestCase.value) {
@@ -124,9 +134,19 @@ const handleTestResult = (e: any) => {
124134
isResponseFile.value = true
125135
} else if(e.body !== ''){
126136
testResult.value.bodyLength = e.body.length
127-
testResult.value.bodyObject = JSON.parse(e.body);
128-
testResult.value.originBodyObject = JSON.parse(e.body);
129-
responseBodyFilter()
137+
try {
138+
// Try to parse as JSON, fallback to plain text if parsing fails
139+
testResult.value.bodyObject = JSON.parse(e.body);
140+
testResult.value.originBodyObject = JSON.parse(e.body);
141+
responseBodyFilter()
142+
} catch (error) {
143+
// This is an expected case for non-JSON responses (like text/plain)
144+
// We intentionally display as plain text instead of attempting JSON parsing
145+
console.debug("Response body is not valid JSON, displaying as plain text:", error);
146+
testResult.value.bodyText = e.body;
147+
testResult.value.bodyObject = null;
148+
testResult.value.originBodyObject = null;
149+
}
130150
}
131151
132152
Cache.SetTestCaseResponseCache(suite + '-' + name, {

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

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,78 @@ limitations under the License.
1515
*/
1616
import { Cache } from './cache'
1717

18-
async function DefaultResponseProcess(response: any) {
18+
/**
19+
* Process HTTP response with proper content type handling
20+
*
21+
* This function handles both JSON and non-JSON responses:
22+
* 1. For JSON responses, parses and returns the JSON object
23+
* 2. For non-JSON responses (like text/plain), returns the raw text
24+
*
25+
* @param response The fetch API response object
26+
* @returns Parsed JSON object or raw text content
27+
*/
28+
async function DefaultResponseProcess(response: any): Promise<any> {
1929
if (!response.ok) {
2030
switch (response.status) {
2131
case 401:
22-
throw new Error("Unauthenticated")
32+
throw new Error("Unauthenticated");
33+
// Potentially add other specific status code handling here
2334
}
2435

25-
const message = await response.json().then((data: any) => data.message)
26-
throw new Error(message)
27-
} else {
28-
return response.json()
36+
// For non-OK responses, attempt to parse error details from the body
37+
let errorMessage = `Request failed with status ${response.status}`;
38+
const clonedResponseForErrorJson = response.clone();
39+
try {
40+
const errorData = await clonedResponseForErrorJson.json();
41+
errorMessage = errorData?.message || JSON.stringify(errorData);
42+
} catch (jsonError: any) {
43+
console.debug(
44+
`Error response body (status ${response.status}) was not valid JSON. Attempting to read as text. JSON parse error:`,
45+
jsonError
46+
);
47+
// Body consumed by failed .json() attempt on clone, try .text() on a new clone of original response
48+
const clonedResponseForErrorText = response.clone();
49+
try {
50+
const textData = await clonedResponseForErrorText.text();
51+
if (textData) {
52+
errorMessage = textData;
53+
} else {
54+
errorMessage = `Request failed with status ${response.status} (empty error body).`;
55+
}
56+
} catch (textError: any) {
57+
console.debug(
58+
`Error response body (status ${response.status}) also failed to be read as text. Text parse error:`,
59+
textError
60+
);
61+
// Fallback error message if body is entirely unreadable
62+
errorMessage = `Request failed with status ${response.status} and error body was unreadable.`;
63+
}
64+
}
65+
throw new Error(errorMessage);
66+
}
67+
68+
// For OK responses, handle content based on Content-Type
69+
const contentType = response.headers.get('Content-Type') ?? '';
70+
if (contentType.startsWith('text/plain')) {
71+
// For text/plain, directly return the text
72+
return await response.text();
73+
}
74+
75+
// For all other types (or if Content-Type is missing/unexpected), try parsing as JSON first
76+
try {
77+
return await response.json();
78+
} catch (jsonParseError: any) {
79+
// This catch block is an intentional part of the content negotiation.
80+
// If the response, despite its Content-Type (or lack thereof), isn't valid JSON,
81+
// we fall back to treating it as plain text. The original error is logged for debugging.
82+
console.debug(
83+
`Response body was not valid JSON (Content-Type: '${contentType}'). Falling back to plain text. JSON parse error:`,
84+
jsonParseError
85+
);
86+
// The body stream was already consumed by the failed response.json() attempt.
87+
// A clone of the original response is needed to read the body as text.
88+
const clonedResponseForTextFallback = response.clone();
89+
return await clonedResponseForTextFallback.text();
2990
}
3091
}
3192

@@ -754,7 +815,12 @@ function GetTestCaseAllHistory(req: TestCase,
754815
.then(callback).catch(errHandle)
755816
}
756817

757-
function DownloadResponseFile(testcase,
818+
interface ResponseFile {
819+
body: string;
820+
[key: string]: any;
821+
}
822+
823+
function DownloadResponseFile(testcase: ResponseFile,
758824
callback: (d: any) => void, errHandle?: (e: any) => void | null) {
759825
const requestOptions = {
760826
method: 'POST',

0 commit comments

Comments
 (0)