简体   繁体   中英

Content-type for application includes charset

I was writing a piece of simple Java code that calls a REST API to mimic the same I did with curl. The curl command sends a POST request to a login end-point:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
"username": "MicroStrategy",
"password": "MyPassword",
"loginMode": 1
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login'

When this succeeds, you get back a 204 HTTP response code and a token as an HTTP Header.

Now, with the following code, I did not get the same result and instead got a HTTP 200 and no token and no body.

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}");
Request urlrequest = new Request.Builder()
   .url("https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login")
   .addHeader("accept", "application/json")
   .post(body)
   .build();
OkHttpClient client = new OkHttpClient();
Response urlresponse = client.newCall(urlrequest).execute();

In the process of trying to understand what I was doing wrong, I ran the request through a reverse proxy (I used "Charles") and realized that the content-type set by okhttp3 was including the charset for application/json:

POST /MicroStrategyLibrary/api/auth/login HTTP/1.1
accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 63
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.8.0
Host: env-792.customer.cloud.microstrategy.com

{"username": "MicroStrategy", "password": "MyPassword", "loginMode": 1}

I verified that the matching curl statement also fails

curl -X POST --header 'Content-Type: application/json; charset=utf-8' --header 'Accept: application/json' -d '{
"username": "MicroStrategy",
"password": "MyPassword",
"loginMode": 1
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login'

Is this a known issue? (it is my understanding that the RFC for content type only allows charset for the text/* content-types; but I'm no expert in that area!)

What can I do to overwrite the Content-Type to remove the charset part?

You are passing your JSON data to RequestBody.create() using a Java String . Per the OkHttp documentation:

\npublic static RequestBody create(@Nullable\n                                 MediaType contentType,\n                                 String content)\n

Returns a new request body that transmits content. If contentType is non-null and lacks a charset, this will use UTF-8.

So, the method you are using intentionally forces UTF-8, so it is likely adding the charset attribute to match.

Try using one of the other create() methods that takes a byte[] or okio.ByteString as input instead of a Java String . They are not documented as forcing UTF-8, since they are taking raw bytes as input, so it is the caller's responsibility to specify a charset only if one is actually needed:

RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}".getBytes(StandardCharsets.UTF_8));

RequestBody body = RequestBody.create(mediaType, okio.ByteString.encodeUtf8("{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM