fix: route RequestBodyPlainText to request_body_data instead of request_body_json#971
Conversation
…st_body_json Co-Authored-By: syed.khadeer@airbyte.io <cloud-support@airbyte.io>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This CDK VersionYou can test this version of the CDK using the following: # Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@devin/1775019092-fix-request-body-plain-text#egg=airbyte-python-cdk[dev]' --help
# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch devin/1775019092-fix-request-body-plain-textPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
PyTest Results (Fast)3 976 tests +1 3 965 ✅ +1 7m 10s ⏱️ -22s Results for commit d023230. ± Comparison against base commit 69cd63d. This pull request removes 4 and adds 5 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
| elif self.request_body.type == "RequestBodyPlainText": | ||
| self.request_body_data = self.request_body.value |
There was a problem hiding this comment.
🔴 Routing change for RequestBodyPlainText breaks backward compatibility with manifest migration
The manifest migration at airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py:54-55 converts request_body_json: <string> into RequestBodyPlainText. Before this PR, RequestBodyPlainText was routed to request_body_json, preserving the original semantics. After this PR, it routes to request_body_data. This means any connector whose manifest contains request_body_json as a string (e.g., conftest.py:719: "request_body_json": '{"nested": ...}') will, after the runtime migration converts it to RequestBodyPlainText, now have its body sent via the data= parameter (URL-encoded form / raw string) instead of the json= parameter (Content-Type: application/json) in http_requester.py:473-478. This silently changes the HTTP wire format for affected connectors, potentially breaking API integrations.
Prompt for agents
The migration at airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py lines 54-55 converts request_body_json string values to RequestBodyPlainText. Now that RequestBodyPlainText routes to request_body_data instead of request_body_json, the migration no longer preserves original semantics. Update the migration's _migrate_body_json method so that when request_body_json is a string, it migrates to a type that still routes to request_body_json (e.g., keep it as RequestBodyJsonObject with the string value, or introduce handling that preserves the JSON body semantics). Alternatively, if the intent is that string-valued request_body_json should indeed become plain text body data, update the migration test fixtures in unit_tests/manifest_migrations/conftest.py accordingly and document the breaking change.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
This concern is addressed in the second commit (d023230d). The migration now skips string-valued request_body_json fields entirely — they are left as request_body_json where InterpolatedNestedRequestInputProvider handles them natively (interpolates the Jinja template, then parses via ast.literal_eval into a dict). This preserves the original JSON body semantics for existing connectors.
Changes:
should_migratereturnsFalsewhen the only migratable key is a stringrequest_body_json_migrate_body_jsonreturns early (no-op) for string valuesvalidateaccepts manifests where stringrequest_body_jsonremains unmigrated- Test fixtures updated accordingly
PyTest Results (Full)3 979 tests +1 3 967 ✅ +1 11m 15s ⏱️ -5s Results for commit d023230. ± Comparison against base commit 69cd63d. This pull request removes 4 and adds 5 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
…migration String-valued request_body_json fields are no longer migrated to RequestBodyPlainText (which now correctly routes to request_body_data). Instead, they are left as request_body_json to preserve their original JSON body semantics via InterpolatedNestedRequestInputProvider. Co-Authored-By: syed.khadeer@airbyte.io <cloud-support@airbyte.io>
Summary
RequestBodyPlainTextwas incorrectly grouped withRequestBodyJsonObjectinInterpolatedRequestOptionsProvider._resolve_request_body(), causing plain text body values to be assigned torequest_body_jsoninstead ofrequest_body_data. This resulted in aValueError("Request body json cannot be a string")whenever a user configured a plain-text request body in the Connector Builder — for example, when creating an asynchronous job with a non-JSON body.The fix splits the combined
elifbranch so thatRequestBodyPlainTextroutes toself.request_body_data(likeRequestBodyUrlEncodedFormalready does), whileRequestBodyJsonObjectcontinues to route toself.request_body_json.Migration backward compatibility
The manifest migration (
HttpRequesterRequestBodyJsonDataToRequestBody) previously converted string-valuedrequest_body_jsonfields toRequestBodyPlainText. Before this fix, that worked by accident becauseRequestBodyPlainTextwas (incorrectly) routed torequest_body_json. Now thatRequestBodyPlainTextcorrectly routes torequest_body_data, the migration would break existing connectors that rely on string JSON templates being sent as JSON bodies.The fix: string-valued
request_body_jsonfields are now skipped by the migration and left asrequest_body_json, whereInterpolatedNestedRequestInputProvideralready handles them natively (interpolating the template string and parsing it viaast.literal_evalinto a dict).Changes to the migration:
should_migratereturnsFalsewhen the only migratable key is a stringrequest_body_json_migrate_body_jsonreturns early (no-op) for string values instead of converting toRequestBodyPlainTextvalidateaccepts manifests where stringrequest_body_jsonremains unmigratedReview & Testing Checklist for Human
request_body_jsonand arequest_body_datakey migrates correctly —request_body_datashould be migrated toRequestBodyUrlEncodedFormwhile the stringrequest_body_jsonis left in place.request_body_json(e.g.,'{"nested": {"key": "{{ config.option }}"}}') continue to send JSON bodies after this change, not raw string data."Request body json cannot be a string"error.{{ config['option'] }}still works correctly inside plain-text body values — the newtest_plain_text_with_interpolationtest covers this, but a manual sanity check is worthwhile.Notes
"test_string"intest_interpolated_request_json_using_request_bodywas encoding the buggy behavior: it expectedRequestBodyPlainTextwith value'{"nested": { "key": "..." }}'to produce a parsed JSON dict. This test has been removed and replaced with two new cases intest_interpolated_request_data_using_request_body.conftest.pyhave been updated so the expected output for stream "D" (stringrequest_body_json) retains the originalrequest_body_jsonkey rather than converting toRequestBodyPlainText.Link to Devin session: https://app.devin.ai/sessions/8a5ed7c6c890468ca63a35469e5c58c1
Requested by: Airbyte Support (@Airbyte-Support)