Skip to content

Fix typo Content-Type header in API client#12

Merged
javlor merged 2 commits intomainfrom
bugfix/fix-typo-header-Content-Type
Apr 24, 2026
Merged

Fix typo Content-Type header in API client#12
javlor merged 2 commits intomainfrom
bugfix/fix-typo-header-Content-Type

Conversation

@javlor
Copy link
Copy Markdown
Collaborator

@javlor javlor commented Apr 21, 2026

Fix typo in the client header that could potentially return HTTP error 415 (unsupported media type). The correct spelling is "Content-Type". See Content-Type header.

@javlor javlor requested a review from iantsednv April 21, 2026 12:09
@iantsednv
Copy link
Copy Markdown
Collaborator

@javlor, this is actually slightly more complicated than I thought. As summarized by review agent:

Background

This fix was reported as necessary to resolve HTTP 415 (Unsupported Media Type) errors in Google Colab. The root cause is real, but the fix is incorrect and introduces a different contract violation that will behave unpredictably across environments.

Why Google Colab returned 415

Google Colab routes outbound traffic through a Google-managed network proxy. With the original "ContentType": "application/json" (no hyphen), the outgoing POST included two relevant headers:

  • ContentType: application/json — a malformed, unrecognised header
  • Content-Type: multipart/form-data; boundary=... — correctly auto-set by requests

The Colab proxy, on encountering the malformed ContentType header alongside a valid Content-Type, appears to have dropped or rewritten the Content-Type before forwarding the request. The server received no valid Content-Type → 415.

Why the proposed fix works in Colab but is wrong

requests sets Content-Type in prepare_body only if it is not already present in the headers (checked via CaseInsensitiveDict):

# from requests/models.py
if content_type and ("content-type" not in self.headers):
    self.headers["Content-Type"] = content_type

By supplying "Content-Type": "application/json" in the shared headers dict, the caller's value wins and requests never overwrites it — even when building a multipart/form-data body with files attached. The server now receives:

  • Content-Type: application/json — declared by our code
  • Body: multipart-encoded binary data with a boundary

This is a broken HTTP request. It works in Colab only because the SolarFarmer API server is lenient and parses the multipart body regardless of the declared Content-Type. Any stricter server, reverse proxy, or future API version will reject it.

Correct fix

Remove Content-Type from the shared headers dict entirely. requests handles it correctly when left alone:

  • GET requests: no body, no Content-Type needed
  • POST with files: auto-set to multipart/form-data; boundary=<boundary>
  • POST without files: auto-set to application/x-www-form-urlencoded
# solarfarmer/api.py — _make_request()
headers = {
    "Authorization": f"Bearer {key}",
    # Content-Type intentionally omitted — requests sets this automatically
    # based on whether files are present (multipart) or not (form-encoded).
    # Forcing it here overrides the boundary parameter and breaks multipart uploads.
    "User-Agent": "solarfarmer-api-sdk/" + __version__,
}

Copy link
Copy Markdown
Collaborator

@iantsednv iantsednv left a comment

Choose a reason for hiding this comment

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

See my comment

@javlor
Copy link
Copy Markdown
Collaborator Author

javlor commented Apr 22, 2026

@ollymaunder-dnv what do you think of the suggestion on Ian's agent to completely remove the Content-Type header?

@javlor javlor merged commit c7a1248 into main Apr 24, 2026
14 checks passed
@javlor javlor deleted the bugfix/fix-typo-header-Content-Type branch April 24, 2026 07:46
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