即使内容类型设置为 application/x-www-form-urlencoded,请求 body 仍作为 json 发送
The request body is sent as json even though the content type is set as application/x-www-form-urlencoded
这与我 (Request Body is not properly encoded and hidden when using spring form encoder in Feign Client) 提出的现有 spring 启动问题有关。
根据 this question,我们可以在 header 中添加内容类型,或者在请求映射本身作为消耗期间添加。
所以我所做的是在客户端配置 headers 中添加内容类型 class
public class EmailClientConfiguration {
@Bean
public RequestInterceptor requestInterceptor(Account<Account> account) {
return template -> {
template.header("Content-Type", "application/x-www-form-urlencoded");
};
}
@Bean
public OkHttpClient client() {
return new OkHttpClient();
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
@Bean
public Encoder feignFormEncoder () {
return new SpringFormEncoder(new JacksonEncoder());
}
}
并且我在 header 中看到发送请求时内容类型被正确设置为 application/x-www-form-urlencoded。但是请求 body 仍然以 json 格式发送并且也没有隐藏。
请求Body:
Map<String, String> requestBody = new HashMap<>();
requestBody.put("username", "xyz");
requestBody.put("email", "xyz@gmail.com");
requestBody.put("key", "xxx");
服务器端收到请求Body:
{"{\n \"key\" : \"xxx\",\n \"email\" : \"xyz@gmail.com\",\n \"username\" : \"xyz\"\n}"
当我在我的请求映射中添加消费时 application/x-www-form-urlencoded
@FeignClient(name = "email", url = "localhost:3000",
configuration = EmailClientConfiguration.class)
public interface EmailClient {
@PostMapping(value = "/email/send", consumes = "application/x-www-form-urlencoded")
ResponseDto sendEmail(@RequestBody Map<String, String> requestBody);
}
它工作正常(请求 body 隐藏在服务器端并且也被正确编码)。当我在配置 class 中删除 header 并仅添加 consumes 时工作正常没有问题但反之亦然有这个问题。
我在互联网上搜索过这个,但找不到任何答案。
Feign 在将请求传递给任何 RequestInterceptor
之前对请求 body 和参数进行编码(这是正确的)。如果您不声明 consumes = "application/x-www-form-urlencoded"
,SprinFormEncoder
不知道您正在尝试发送表单数据,因此它会将序列化委托给内部 JacksonEncoder
,它只执行 JSON (通过在设置 header 之前打印 template.body()
自己查看)。
在拦截器中处理这样的 well-supported header 似乎不是一个好主意,因为您已经有 consumes
。如果你坚持这样做,你必须提供你自己的编码器,它不依赖于 header 值并且总是输出 form-urlencoded 数据。
这与我 (Request Body is not properly encoded and hidden when using spring form encoder in Feign Client) 提出的现有 spring 启动问题有关。
根据 this question,我们可以在 header 中添加内容类型,或者在请求映射本身作为消耗期间添加。
所以我所做的是在客户端配置 headers 中添加内容类型 class
public class EmailClientConfiguration {
@Bean
public RequestInterceptor requestInterceptor(Account<Account> account) {
return template -> {
template.header("Content-Type", "application/x-www-form-urlencoded");
};
}
@Bean
public OkHttpClient client() {
return new OkHttpClient();
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
@Bean
public Encoder feignFormEncoder () {
return new SpringFormEncoder(new JacksonEncoder());
}
}
并且我在 header 中看到发送请求时内容类型被正确设置为 application/x-www-form-urlencoded。但是请求 body 仍然以 json 格式发送并且也没有隐藏。
请求Body:
Map<String, String> requestBody = new HashMap<>();
requestBody.put("username", "xyz");
requestBody.put("email", "xyz@gmail.com");
requestBody.put("key", "xxx");
服务器端收到请求Body:
{"{\n \"key\" : \"xxx\",\n \"email\" : \"xyz@gmail.com\",\n \"username\" : \"xyz\"\n}"
当我在我的请求映射中添加消费时 application/x-www-form-urlencoded
@FeignClient(name = "email", url = "localhost:3000",
configuration = EmailClientConfiguration.class)
public interface EmailClient {
@PostMapping(value = "/email/send", consumes = "application/x-www-form-urlencoded")
ResponseDto sendEmail(@RequestBody Map<String, String> requestBody);
}
它工作正常(请求 body 隐藏在服务器端并且也被正确编码)。当我在配置 class 中删除 header 并仅添加 consumes 时工作正常没有问题但反之亦然有这个问题。
我在互联网上搜索过这个,但找不到任何答案。
Feign 在将请求传递给任何 RequestInterceptor
之前对请求 body 和参数进行编码(这是正确的)。如果您不声明 consumes = "application/x-www-form-urlencoded"
,SprinFormEncoder
不知道您正在尝试发送表单数据,因此它会将序列化委托给内部 JacksonEncoder
,它只执行 JSON (通过在设置 header 之前打印 template.body()
自己查看)。
在拦截器中处理这样的 well-supported header 似乎不是一个好主意,因为您已经有 consumes
。如果你坚持这样做,你必须提供你自己的编码器,它不依赖于 header 值并且总是输出 form-urlencoded 数据。