codeant-ai-for-open-source[bot] commented on code in PR #37131:
URL: https://github.com/apache/superset/pull/37131#discussion_r3402738627
##########
superset-frontend/packages/superset-ui-core/src/connection/SupersetClientClass.ts:
##########
@@ -150,6 +150,25 @@ export default class SupersetClientClass {
}
}
+ /**
+ * POST request that returns a blob for file downloads.
+ * Unlike postForm, this uses AJAX so errors can be caught and handled.
+ * @param endpoint - API endpoint
+ * @param payload - Request payload
+ * @returns Promise resolving to Response with blob
+ */
+ async postBlob(
+ endpoint: string,
+ payload: Record<string, any>,
+ ): Promise<Response> {
+ await this.ensureAuth();
+ return this.post({
+ endpoint,
+ postPayload: payload,
+ parseMethod: 'raw',
+ });
Review Comment:
**Suggestion:** `postBlob` forwards `postPayload` without overriding the
default `stringify: true`, so string fields are JSON-stringified again by
`callApi`. Export callers already pass `form_data` as a JSON string, which
becomes double-encoded (extra quotes), and the backend then parses it as a
string instead of an object, causing export requests to fail (typically 400)
instead of downloading. Pass `stringify: false` (or send a prebuilt `FormData`)
to preserve raw form field values. [api mismatch]
<details>
<summary><b>Severity Level:</b> Critical 🚨</summary>
```mdx
- ❌ Dashboard chart CSV export returns HTTP 400, no download.
- ❌ Explore view chart exports fail against /api/v1/chart/data.
- ⚠️ Users see error toasts instead of downloaded export files.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Open a dashboard and trigger CSV export for a chart; tests at
`superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.test.tsx:8-31`
show
that clicking "Export to .CSV" calls `exportChart(...)` from
`src/explore/exploreUtils/index.ts`.
2. In
`superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.tsx:19-37,559-567`,
the `exportChart` function is invoked with `resultFormat: 'csv'` and
`resultType: 'full'`,
and `onStartStreamingExport` left as `null`, so the non-streaming export
path is used.
3. Inside `superset-frontend/src/explore/exploreUtils/index.ts:18-69`,
`exportChart`
builds the payload and, for the v1 API (`url = '/api/v1/chart/data'`), calls
`SupersetClient.postBlob(url as string, { form_data: safeStringify(payload)
})` at lines
41-47 and 65-67, where `safeStringify` (see
`plugins/preset-chart-deckgl/src/utils/safeStringify.ts:4-24`) returns a
JSON string.
4. `SupersetClient.postBlob` in
`packages/superset-ui-core/src/connection/SupersetClientClass.ts:160-169`
forwards this
payload via `this.post({ endpoint, postPayload: payload, parseMethod: 'raw'
})` without
specifying `stringify`, so `request` flows into `callApiAndParseWithTimeout`
and then
`callApi` in
`packages/superset-ui-core/src/connection/callApi/callApi.ts:8-23,80-100`,
where `stringify` defaults to `true` and each form field value is
transformed with
`valueString = stringify ? JSON.stringify(value) : String(value)`, causing
`form_data`
(already a JSON string) to be JSON-stringified again and sent as `'"{...}"'`
in the
multipart form body.
5. On the backend, `superset/charts/data/api.py:47-55` handles
`/api/v1/chart/data` POST
requests by checking `request.form.get("form_data")` and running
`json.loads(request.form["form_data"])`; with the double-encoded payload
this produces a
plain string instead of a dict, so `_create_query_context_from_form` (which
expects a
dict, see `superset/tasks/async_queries.py:1-14`) raises a
`ValidationError`, and
`ChartDataRestApi.data` catches this and returns `self.response_400(...)`,
causing the
chart export HTTP 400 error and preventing the file from downloading.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=e7b9856f660c40e4b8dcb258ecd148d2&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
| [Fix in VSCode
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=e7b9856f660c40e4b8dcb258ecd148d2&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:**
superset-frontend/packages/superset-ui-core/src/connection/SupersetClientClass.ts
**Line:** 165:169
**Comment:**
*Api Mismatch: `postBlob` forwards `postPayload` without overriding the
default `stringify: true`, so string fields are JSON-stringified again by
`callApi`. Export callers already pass `form_data` as a JSON string, which
becomes double-encoded (extra quotes), and the backend then parses it as a
string instead of an object, causing export requests to fail (typically 400)
instead of downloading. Pass `stringify: false` (or send a prebuilt `FormData`)
to preserve raw form field values.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37131&comment_hash=8b1f48b41e65b204a160b00ca6d3fd7fdc21765f471ee95fb8e94beee87fca14&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37131&comment_hash=8b1f48b41e65b204a160b00ca6d3fd7fdc21765f471ee95fb8e94beee87fca14&reaction=dislike'>👎</a>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]