使用 ClientBuilder 发送 JSON body 但 ContentType=application/x-www-form-urlencoded
Send JSON body but with ContentType=application/x-www-form-urlencoded with ClientBuilder
我知道这个问题很奇怪。不幸的是,我有一项服务要求所有内容都具有 header ContentType=application/x-www-form-urlencoded
,尽管 body 是 JSON
我正在尝试使用 JAX-RS 2.0 ClientBuilder 来调用它:
String baseUrl = "http://api.example.com/";
JSONObject body = new JSONObject();
body.put("key", "value");
Client client = ClientBuilder.newClient();
client.register(new LoggingFilter());
Builder builder = client.target(baseUrl).path("something").request();
Invocation inv = builder
.header("Content-type", MediaType.APPLICATION_FORM_URLENCODED)
.buildPost(Entity.json(body));
Response response = inv.invoke();
int status = response.getStatus();
// I get 415, unsupported media type (in this case is unexpected)
我已经检查了我的日志,尽管我正在设置 application/x-www-form-urlencoded
(通过 MediaType
),但请求似乎具有 application/json
[=22= 的 Content-type
]
如何强制请求获得我想要的Content-type
?
顺便说一句:这是我的自定义记录器:
public class LoggingFilter implements ClientRequestFilter {
private static final Logger LOG = Logger.getLogger(LoggingFilter.class.getName());
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
LOG.log(Level.INFO, "body");
LOG.log(Level.INFO, requestContext.getEntity().toString());
LOG.log(Level.INFO, "headers");
LOG.log(Level.INFO, requestContext.getHeaders().toString());
}
}
这些是我得到的日志:
com.acme.LoggingFilter I body
com.acme.LoggingFilter I {"key":"value"}
com.acme.LoggingFilter I headers
com.acme.LoggingFilter I {Content-type=[application/json]}
尝试使用静态 Entity
辅助方法之一的问题是它会覆盖您之前可能设置的任何 Content-Type
header。在您当前的情况下,Entity.json
会自动将 header 设置为 application/json
。
您可以只使用通用的 Entity.entity(Object, MediaType)
方法,而不是使用 .json
方法。不过,对于您当前的情况,您可以 Entity.entity(body, MediaType.APPLICATION_FORM_URLENCODED_TYPE)
。原因是客户端会寻找知道如何序列化 JSONObject
到 application/x-www-form-urlencoded
数据的提供程序,其中有 none。所以你需要先将它序列化为一个字符串。这样,处理 application/x-www-form-urlencoded
的提供程序就不需要序列化任何内容。所以就这样做
Entity.entity(body.toString(), MediaType.APPLICATION_FORM_URLENCODED_TYPE);
我知道这个问题很奇怪。不幸的是,我有一项服务要求所有内容都具有 header ContentType=application/x-www-form-urlencoded
,尽管 body 是 JSON
我正在尝试使用 JAX-RS 2.0 ClientBuilder 来调用它:
String baseUrl = "http://api.example.com/";
JSONObject body = new JSONObject();
body.put("key", "value");
Client client = ClientBuilder.newClient();
client.register(new LoggingFilter());
Builder builder = client.target(baseUrl).path("something").request();
Invocation inv = builder
.header("Content-type", MediaType.APPLICATION_FORM_URLENCODED)
.buildPost(Entity.json(body));
Response response = inv.invoke();
int status = response.getStatus();
// I get 415, unsupported media type (in this case is unexpected)
我已经检查了我的日志,尽管我正在设置 application/x-www-form-urlencoded
(通过 MediaType
),但请求似乎具有 application/json
[=22= 的 Content-type
]
如何强制请求获得我想要的Content-type
?
顺便说一句:这是我的自定义记录器:
public class LoggingFilter implements ClientRequestFilter {
private static final Logger LOG = Logger.getLogger(LoggingFilter.class.getName());
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
LOG.log(Level.INFO, "body");
LOG.log(Level.INFO, requestContext.getEntity().toString());
LOG.log(Level.INFO, "headers");
LOG.log(Level.INFO, requestContext.getHeaders().toString());
}
}
这些是我得到的日志:
com.acme.LoggingFilter I body
com.acme.LoggingFilter I {"key":"value"}
com.acme.LoggingFilter I headers
com.acme.LoggingFilter I {Content-type=[application/json]}
尝试使用静态 Entity
辅助方法之一的问题是它会覆盖您之前可能设置的任何 Content-Type
header。在您当前的情况下,Entity.json
会自动将 header 设置为 application/json
。
您可以只使用通用的 Entity.entity(Object, MediaType)
方法,而不是使用 .json
方法。不过,对于您当前的情况,您可以 Entity.entity(body, MediaType.APPLICATION_FORM_URLENCODED_TYPE)
。原因是客户端会寻找知道如何序列化 JSONObject
到 application/x-www-form-urlencoded
数据的提供程序,其中有 none。所以你需要先将它序列化为一个字符串。这样,处理 application/x-www-form-urlencoded
的提供程序就不需要序列化任何内容。所以就这样做
Entity.entity(body.toString(), MediaType.APPLICATION_FORM_URLENCODED_TYPE);