Skip to content

fix(jinja): handle non-JSON body with JSON content-type in get_form_data#42196

Open
aminghadersohi wants to merge 2 commits into
apache:masterfrom
aminghadersohi:fix-mcp-filter-values-form-data-badrequest-2026-07-18
Open

fix(jinja): handle non-JSON body with JSON content-type in get_form_data#42196
aminghadersohi wants to merge 2 commits into
apache:masterfrom
aminghadersohi:fix-mcp-filter-values-form-data-badrequest-2026-07-18

Conversation

@aminghadersohi

Copy link
Copy Markdown
Contributor

SUMMARY

get_form_data() crashed with an unhandled werkzeug.exceptions.BadRequest whenever it ran inside a request context where the Content-Type header claimed JSON but the body wasn't actually parseable JSON. This happens for any caller that reaches get_form_data() outside a normal chart-data POST — for example the filter_values() / get_filters() Jinja macros used in chart and dataset SQL templates, when rendered from a request context that isn't a real chart-data request.

request.is_json only inspects the Content-Type header; it does not guarantee the body is valid, non-empty JSON. get_form_data() already has a helper, loads_request_json(), that gracefully falls back to {} on a JSON parse failure — but that guard was only applied to the request.form / request.args fallback paths, not to the primary request.get_json(cache=True) call, which is the one that was actually raising.

This PR extracts the JSON-body parsing into a small get_request_json_body() helper that catches BadRequest and falls back to {}, matching the existing loads_request_json() behavior.

Internal tracking: SC-114072

TESTING INSTRUCTIONS

  • Added tests/unit_tests/views/test_utils.py::test_get_form_data_handles_non_json_body_with_json_content_type, which builds a request context with Content-Type: application/json and a non-JSON body, and asserts get_form_data() returns ({}, None) instead of raising.
  • pytest tests/unit_tests/views/test_utils.py tests/unit_tests/jinja_context_test.py -q — 104 passed.
  • Manually reproduced the crash against master (request.get_json(cache=True) raising BadRequest) and confirmed the fix resolves it via app.test_request_context(data="not-json-at-all", content_type="application/json").

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

request.is_json only inspects the Content-Type header, not whether the
body is actually parseable JSON. When a request context has that shape
(as happens when an MCP tool call renders a filter_values() template),
request.get_json() raises an uncaught werkzeug.exceptions.BadRequest
that propagates through Jinja rendering. Fall back to {} instead, the
same way loads_request_json() already does for the request.form and
request.args paths.
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.19%. Comparing base (751f5eb) to head (11bd30e).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
superset/views/utils.py 77.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42196      +/-   ##
==========================================
- Coverage   65.19%   65.19%   -0.01%     
==========================================
  Files        2767     2767              
  Lines      156062   156064       +2     
  Branches    35717    35715       -2     
==========================================
+ Hits       101741   101742       +1     
- Misses      52361    52362       +1     
  Partials     1960     1960              
Flag Coverage Δ
hive 38.60% <22.22%> (-0.01%) ⬇️
mysql 57.86% <77.77%> (+<0.01%) ⬆️
postgres 57.92% <77.77%> (+<0.01%) ⬆️
presto 40.54% <44.44%> (-0.01%) ⬇️
python 59.33% <77.77%> (+<0.01%) ⬆️
sqlite 57.54% <77.77%> (+<0.01%) ⬆️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aminghadersohi
aminghadersohi marked this pull request as ready for review July 18, 2026 20:21
@dosubot dosubot Bot added the global:jinja Related to Jinja templating label Jul 18, 2026
@bito-code-review

bito-code-review Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #63474f

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: e89540c..11bd30e
    • superset/views/utils.py
    • tests/unit_tests/views/test_utils.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

global:jinja Related to Jinja templating size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant