Skip to content

Conversation

@nafees87n
Copy link
Contributor

@nafees87n nafees87n commented Jan 23, 2026

In application/json requests when the body string is not a valid json axios automatically stringifies it.

Refer axios' implementation: default transformRequest and safelyStringify.

As this is core of our API client, we want the users to have control over what data format they need to send instead of implicitly transforming the data.

Solution

This PR bypasses axios' default transformation when content type is application/json and allows the data to be sent as is, in raw form, if request data is not a valid JSON string.

Summary by CodeRabbit

  • Bug Fixes
    • More reliable multipart/form-data handling: skips non-file entries and consistently appends files.
    • Standardized content-type detection to respect headers case-insensitively.
    • Improved JSON request handling: detects pre-parsed JSON strings and sends raw body when parsing fails to avoid double-stringification.
    • Ensured request serialization behavior aligns with resolved content type.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Jan 23, 2026

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

Walkthrough

Updates to src/main/actions/makeApiClientRequest.js: multipart/form-data handling reworked to map entries to { stream, fileName }, filter non-streams, and append files via destructuring; content-type header lookup now uses case-insensitive header key before falling back to apiRequest.contentType; adds JSON-aware Axios transformRequest: detects application/json (header or apiRequest.contentType), attempts JSON.parse for string bodies and, on parse failure, sets a transform to bypass Axios default JSON stringification to send the raw body. Minor formatting and indentation adjustments. Lines changed: +51/-14.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the specific bug being fixed: axios double stringifying request bodies when sent with application/json content-type, which is the main focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nafees87n nafees87n requested a review from wrongsahil January 23, 2026 08:58
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/main/actions/makeApiClientRequest.js`:
- Around line 79-86: The code that determines requestContentType uses raw header
values, so normalize the Content-Type before comparison: when computing
requestContentType from headers (symbol: requestContentType and headers) trim
it, lowercase it and strip any parameters after ';' (e.g., split on ';' and take
the first token), and do the same normalization to apiRequest.contentType before
any equality checks; update places that compare requestContentType to
apiRequest.contentType to use these normalized values to ensure
JSON/content-type matching works regardless of case or charset parameters.
- Around line 71-73: The Content-Type bug is caused by template-stringifying
formData.getHeaders(), which yields "[object Object]"; in
makeApiClientRequest.js, change the headers construction to merge the object
returned by formData.getHeaders() instead of stringifying it: retrieve
formData.getHeaders() (via variable like formHeaders) and spread its properties
into the headers object (e.g., ...formHeaders, ...headers) so the multipart
boundary header is preserved and not turned into a string.
🧹 Nitpick comments (1)
src/main/actions/makeApiClientRequest.js (1)

41-62: Use path.basename for cross‑platform filenames.

entry.path.split("/") fails on Windows paths. Prefer path.basename to handle both / and \.

♻️ Suggested change
+const path = require("path");
 ...
-                  fileName: entry.name || entry.path.split("/").pop(),
+                  fileName: entry.name || path.basename(entry.path),

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/main/actions/makeApiClientRequest.js`:
- Around line 90-94: The check in makeApiClientRequest.js calls
requestContentType.includes(...) without ensuring requestContentType exists;
update the guard so it first ensures a string (or non-null) before calling
includes — for example coerce requestContentType to an empty string or use a
truthy check like requestContentType &&
requestContentType.includes("application/json") — then proceed with the typeof
body === "string" check; make this change around the requestContentType, body
and apiRequest.contentType usage so missing headers/apiRequest.contentType won't
throw.
♻️ Duplicate comments (1)
src/main/actions/makeApiClientRequest.js (1)

70-73: Fix multipart Content‑Type header assembly.

Stringifying formData.getHeaders() yields "[object Object]", producing an invalid header. Merge the returned object instead.

✅ Suggested fix
       body = formData;
       headers = {
-        "content-type": `${formData.getHeaders()}`,
+        ...formData.getHeaders(),
         ...headers,
       };

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/main/actions/makeApiClientRequest.js`:
- Around line 84-91: The fallback path for JSON detection uses strict equality
on apiRequest.contentType which fails for casing or charset variants; update the
fallback in makeApiClientRequest (the block using contentTypeHeader and
apiRequest.contentType) to mirror the header normalization: check
apiRequest.contentType?.toLowerCase()?.includes("application/json") (guarding
for null/undefined) instead of === "application/json" so charset and case
variants are treated as JSON.
♻️ Duplicate comments (1)
src/main/actions/makeApiClientRequest.js (1)

70-73: Bug: multipart Content-Type header becomes "[object Object]".

formData.getHeaders() returns an object; template-stringifying it yields "[object Object]", which is an invalid header value and breaks multipart uploads.

Suggested fix
      headers = {
-       "content-type": `${formData.getHeaders()}`,
+       ...formData.getHeaders(),
        ...headers,
      };

Comment on lines +84 to +91
if (contentTypeHeader) {
return headers[contentTypeHeader]
?.toLowerCase()
?.includes("application/json");
}

return apiRequest.contentType === "application/json";
})();
Copy link

@coderabbitai coderabbitai bot Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent Content-Type normalization in fallback path.

The header check normalizes (lowercase + includes), but the fallback uses strict equality on apiRequest.contentType. If apiRequest.contentType contains charset params or different casing (e.g., "application/json; charset=utf-8"), the fallback will incorrectly return false.

Suggested fix
      if (contentTypeHeader) {
        return headers[contentTypeHeader]
          ?.toLowerCase()
          ?.includes("application/json");
      }

-     return apiRequest.contentType === "application/json";
+     return apiRequest.contentType
+       ?.toLowerCase()
+       ?.includes("application/json");
    })();
🤖 Prompt for AI Agents
In `@src/main/actions/makeApiClientRequest.js` around lines 84 - 91, The fallback
path for JSON detection uses strict equality on apiRequest.contentType which
fails for casing or charset variants; update the fallback in
makeApiClientRequest (the block using contentTypeHeader and
apiRequest.contentType) to mirror the header normalization: check
apiRequest.contentType?.toLowerCase()?.includes("application/json") (guarding
for null/undefined) instead of === "application/json" so charset and case
variants are treated as JSON.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apiRequest.contentType would not have anything else because it uses our custom enum in the UI

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nafees87n, thank you for the clarification! That makes sense—if apiRequest.contentType is restricted to a custom enum in the UI, then the strict equality check is appropriate and safe. The normalization concern only applies to the headers path where values can be arbitrary.

The current implementation is fine as-is.


✏️ Learnings added
Learnt from: nafees87n
Repo: requestly/requestly-desktop-app PR: 272
File: src/main/actions/makeApiClientRequest.js:84-91
Timestamp: 2026-01-23T12:09:53.004Z
Learning: In `src/main/actions/makeApiClientRequest.js`, the `apiRequest.contentType` field uses a custom enum defined in the UI, so it will always be an exact value like `"application/json"` without charset parameters or casing variants. Strict equality checks against `apiRequest.contentType` are safe and appropriate.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants