Spring RestTemplate调用CloudFlare API抛出InvalidMediaTypeException异常
根本原因
CloudFlare返回的Content-Type响应头不符合RFC规范:正常带参数的MIME类型格式应为text/plain; charset=UTF-8(类型与参数之间用分号分隔),但目前返回的是text/plain charset=UTF-8(错用空格分隔)。Spring框架的MIME类型解析默认严格校验格式,因此直接抛出异常。你的业务代码没有逻辑问题,故障是服务端响应头格式错误导致。
可行解决方案
按优先推荐顺序排列:
- 方案1:新增响应拦截器修复错误头
给RestTemplate添加自定义拦截器,收到响应后先修复格式异常的Content-Type头,再交给后续逻辑处理,侵入性最低,不影响其他业务逻辑:
public class CloudFlareContentTypeFixInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { ClientHttpResponse response = execution.execute(request, body); HttpHeaders headers = response.getHeaders(); String rawContentType = headers.getFirst(HttpHeaders.CONTENT_TYPE); // 匹配本次遇到的无分号错误格式 if (rawContentType != null && rawContentType.startsWith("text/plain ") && !rawContentType.contains(";")) { String fixedContentType = rawContentType.replaceFirst(" ", "; "); headers.set(HttpHeaders.CONTENT_TYPE, fixedContentType); } return response; } } // 注册拦截器到RestTemplate restTemplate.setInterceptors(Collections.singletonList(new CloudFlareContentTypeFixInterceptor()));
- 方案2:自定义字符串消息转换器跳过校验
你当前请求指定了返回值为String.class,可以自定义StringHttpMessageConverter,强制不校验响应ContentType,直接按字符串解析:
// 自定义转换器优先处理String类型返回值,忽略ContentType校验 StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8) { @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return String.class == clazz; } }; // 加到转换器列表最前面,优先生效 restTemplate.getMessageConverters().add(0, stringConverter);
- 方案3:全局关闭MIME严格校验
如果多处调用该API,可以通过设置系统参数全局降低Spring MIME解析的严格程度,适合内部业务可控的场景:
在项目启动参数中添加:-Dorg.springframework.util.MimeTypeUtils.parsingStrict=false
或者在启动类静态代码块中配置:
static { System.setProperty("org.springframework.util.MimeTypeUtils.parsingStrict", "false"); }
多线程场景注意
RestTemplate本身是线程安全的,毫秒级高并发调用场景下不要每次请求都新建RestTemplate实例,全局复用同一个即可,避免不必要的资源开销。
内容的提问来源于stack exchange,提问作者Jabalnur Lazim
相关产品推荐
相关产品推荐

