如何解决即使内容类型设置为 application/x-www-form-urlencoded,请求正文仍作为 json 发送
这与我 (Request Body is not properly encoded and hidden when using spring form encoder in Feign Client) 提出的现有 Spring Boot 问题有关。
根据this question,我们可以在标头中添加内容类型,也可以在请求映射期间将其自身添加为消费。
所以我所做的是在客户端配置类的标题中添加内容类型
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());
}
}
并且我在标题中看到内容类型在发送请求时正确设置为 application/x-www-form-urlencoded。但是请求体仍然以json格式发送,也没有隐藏。
请求正文:
Map<String,String> requestBody = new HashMap<>();
requestBody.put("username","xyz");
requestBody.put("email","xyz@gmail.com");
requestBody.put("key","xxx");
服务器端收到的请求正文:
{"{\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);
}
它工作正常(请求正文隐藏在服务器端并且也正确编码)。当我删除配置类中的标头并仅添加消耗时,它可以正常工作而没有任何问题,但反之亦然有这个问题。
我在互联网上搜索了这个,但找不到任何答案。
解决方法
Feign 在将请求传递给任何 RequestInterceptor
之前对请求正文和参数进行编码(这是正确的)。如果您不声明 consumes = "application/x-www-form-urlencoded"
,SprinFormEncoder
不知道您正在尝试发送表单数据,因此它将序列化委托给仅执行 JSON 的内部 JacksonEncoder
(请参阅通过在设置标题之前打印 template.body()
)。
当您已经有了 consumes
时,在拦截器中处理如此受支持的标头似乎不是一个好主意。如果您坚持这样做,您必须提供自己的编码器,该编码器不依赖于标头值并始终输出表单 urlencoded 数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。