应用程序的内容类型包括charset

时间:2017-09-25 20:06:22

标签: json rest curl character-encoding content-type

我正在编写一段简单的Java代码,它调用REST API来模仿与curl相同的代码。 curl命令向登录端点发送POST请求:

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'

如果成功,您将获得204 HTTP响应代码和一个令牌作为HTTP标头。

现在,使用以下代码,我没有得到相同的结果,而是得到了一个HTTP 200,没有令牌,没有正文。

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();

在尝试理解我做错了什么的过程中,我通过反向代理(我使用" Charles")运行请求,并意识到okhttp3设置的内容类型包括charset申请/ 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}

我验证了匹配的curl语句也失败了

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'

这是一个已知问题吗? (据我所知,内容类型的RFC只允许charset用于text / * content-types;但我不是该领域的专家!)

如何覆盖Content-Type以删除charset部分?

1 个答案:

答案 0 :(得分:1)

您正在使用Java String将JSON数据传递给RequestBody.create()。根据OkHttp文档:

public static RequestBody create(@Nullable
                                 MediaType contentType,
                                 String content)
     

返回传输内容的新请求正文。 如果contentType为非null且缺少字符集,则使用UTF-8。

因此,您使用的方法会强制强制使用UTF-8,因此可能会添加charset属性以进行匹配。

尝试使用以create()byte[]作为输入而不是Java okio.ByteString的其他String方法之一。它们没有记录为强制UTF-8,因为它们将原始字节作为输入,因此只有在实际需要时才指定charset是调用者的责任:

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}"));