【问题标题】:Content-type for application includes charset应用程序的内容类型包括字符集
【发布时间】:2018-03-06 21:41:53
【问题描述】:

我正在编写一段简单的 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 设置的内容类型包括 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}

我验证了匹配的 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 仅允许 text/* 内容类型的字符集;但我不是该领域的专家!)

如何覆盖 Content-Type 以删除字符集部分?

【问题讨论】:

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


    【解决方案1】:

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

    公共静态 RequestBody 创建(@Nullable 媒体类型内容类型, 字符串内容)

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

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

    尝试使用将byte[]okio.ByteString 作为输入而不是Java String 的其他create() 方法之一。它们没有被记录为强制 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}"));
    

    【讨论】:

    • 我确认使用create()byte[] 输入有效。我不喜欢使用解决方法,但这对我来说就足够了! :)
    猜你喜欢
    • 2014-06-03
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 2019-12-21
    • 2021-07-03
    • 2010-12-20
    • 1970-01-01
    相关资源
    最近更新 更多