-
Notifications
You must be signed in to change notification settings - Fork 24.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent okhttp from adding ;charset=utf8 to ContentType Header #23580
Conversation
Before this commit, fetch() calls include "charset=utf8" on Android. This is because of an implementation detail in the okhttp library. Passing byte array into the RequestBody avoids this, as recommended by a maintainer of okhttp: square/okhttp#2099 (comment) Related issues: facebook#8237
@@ -309,6 +309,55 @@ public Object answer(InvocationOnMock invocation) throws Throwable { | |||
assertThat(requestHeaders.get("User-Agent")).isEqualTo("React test agent/1.0"); | |||
} | |||
|
|||
@Test | |||
public void testPostJsonContentTypeHeader() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from previous tests. It's possible more of the mocks below can be removed. Any thoughts?
This is actually a pretty simple fix for a long going problem for many 👍 import com.facebook.react.common.StandardCharsets;
body.getBytes(StandardCharsets.UTF_8) For unit tests, you're heavily mocking OkHttp. Was the test actually failing as intended when you undo your fix? |
@hey99xx good deal, 👍. I wondered about that, or passing in the character set as defined by The new test fails without this change. I get the following failure:
I'd love to actually assert the headers that OkHTTP is building. This was the closest I could manage to get. |
@nhunzaker I'm not sure I understand your last comment. Can you confirm that @hey99xx's concern is addressed? |
I was able to drop mocks for events and I limited the test assertions strictly to testing the content type.
Regarding:
Yes, I believe I have. While the test heavily mocks OkHttp, the important part to test is the stringification of the MediaType class, which is not mocked. I sent out another commit that I hope simplifies the test and makes that clearer (https://github.com/facebook/react-native/pull/23580/files#diff-0a0a7fd9969f1f5f68d80bf421fcc092R346). Without my change, this fails, returning |
@nhunzaker I mean this part: "Can we still specify utf8 as the charset for the bytes though?" – I assume the answer is yes, just wanna hear the confirmation. |
@cpojer Oh! Sorry, yep! This line should do it: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks for clarifying. Let's ship it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if my approval matters after @cpojer 's, but here you go anyways
Yes it definitely does matter |
@nhunzaker merged commit 4a80776 into |
Summary: Before this commit, `fetch()` calls append `"charset=utf8"` to the `Content-Type` header on Android (and not on iOS). This is because of an implementation detail in the okhttp library. This means that you can make a call on the JavaScript side like: ```javascript let body = JSON.stringify({ key: "value" }); let headers = { "Content-Type": "application/json" }; fetch("http://10.0.2.2:3000", { method: "POST", body, headers }); ``` However the resulting request appends the utf8 character: ``` POST - 13:34:32: content-type: application/json; charset=utf-8 content-length: 15 host: 10.0.2.2:3000 connection: Keep-Alive accept-encoding: gzip user-agent: okhttp/3.12.1 ``` Passing byte array into the RequestBody avoids this, as recommended by a maintainer of okhttp: square/okhttp#2099 (comment) Related issues: #8237 [Android][fixed] - Prevent fetch() POST requests on Android from appending `charset=utf-8` to `Content-Type` header. Pull Request resolved: #23580 Differential Revision: D14180849 Pulled By: cpojer fbshipit-source-id: b84cadf83361331a9f64d1ff5f2e6399a55527a6
Summary
Before this commit,
fetch()
calls append"charset=utf8"
to theContent-Type
header on Android (and not on iOS). This is because of an implementation detail in the okhttp library. This means that you can make a call on the JavaScript side like:However the resulting request appends the utf8 character:
Passing byte array into the RequestBody avoids this, as recommended by a maintainer of okhttp:
square/okhttp#2099 (comment)
Related issues:
#8237
Changelog
[Android][fixed] - Prevent fetch() POST requests on Android from appending
charset=utf-8
toContent-Type
header.Test Plan
I setup a test project here: https://github.com/nhunzaker/rn-charset-issue. It includes a simple node server that logs header output from requests. With this change, the server no longer reports the addition of
charset=utf-8
in theContent-Type
header.