获取 .com 电子邮件地址的请求失败,因为 Spring 将其解释为扩展名
Get Request fails for .com email addresses because Spring interpretes it as a extensions
(见 2015 年 8 月 20 日下方的编辑部分)
我最近遇到了类似的问题 () and the solution was to add a regex to the value of @RequestMapping (see also Spring MVC @PathVariable getting truncated)。
但现在我们意识到问题仍然存在,但仅限于以 .com 或 .org 结尾的电子邮件地址。这很奇怪。
很快,我使用 Spring 注释构建 REST 服务。我有一个包含三个参数的 GET 请求,最后一个是电子邮件。
我的控制器:
@RequestMapping(method = GET, value = "/{value1}/{value2}/{value3:.+}",
produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
public ResponseEntity<MyResponseType> getMyResource(
@ApiParam(value = "...",...)
@PathVariable("value1") String value1,
@ApiParam(value = "...",...)
@PathVariable("value2") String value2,
@ApiParam(value = "...",...)
@PathVariable("value3") String value3) {
//...
}
如果我调用:
http://myserver:8080/myresource/value1/value2/value3
用value3=email@domain.de/co.uk/.name/.biz/.info,完全没有问题。
但对于某些顶级域(目前为 .com、.org),我收到 Http 状态代码 406(未接受)。
如果我添加尾部斜杠,它会起作用:
http://myserver:8080/myresource/value1/value2/value3/
由于我们使用 swagger 并且 swagger 不添加尾部斜杠,因此添加尾部斜杠不是一个选项。
什么可能导致此问题?
我使用了一个扩展 ResponseEntityExceptionHandler 的 ErrorHandler。
我调试了一下,发现抛出了HttpMediaTypeNotAcceptableException ("Could not find acceptable representation")。但是我还不知道是谁扔的,为什么扔。
编辑
我发现路径 http://myserver:8080/myresource/value1/value2/myemail@somewhere.com
被解释为文件,而"com"是媒体类型"application/x-msdownload"的文件扩展名,所以在Spring的classProducesRequestCondition.ProduceMediaTypeExpression中"getMediaType().isCompatibleWith(acceptedMediaType)" 行的 matchMediaType 方法失败,因为实际生成的媒体类型是 "application/json;charset=UTF-8",而不是 "application/x-msdownload"。
所以问题变为:我怎样才能让 Spring 明白 .com 不是文件扩展名?
这个帖子帮助了我:
SpringMVC: Inconsistent mapping behavior depending on url extension
显然这不是错误而是 "feature" 并且有两种不同的方法可以禁用它。我用的注释版本:
@Configuration
@EnableWebMvc
public class RestCommonsMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
我从 spring 3.1.2 升级到 3.2.7 时遇到了这个问题。 的回答帮助了我(应该标记为答案)。但是我没有扩展 WebMvcConfigurerAdapter
,而是在我的 WebConfig
中扩展了 WebMvcConfigurationSupport
。
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
super.configureContentNegotiation(configurer);
configurer.favorPathExtension(false).favorParameter(true);
}
}
(见 2015 年 8 月 20 日下方的编辑部分)
我最近遇到了类似的问题 (
但现在我们意识到问题仍然存在,但仅限于以 .com 或 .org 结尾的电子邮件地址。这很奇怪。
很快,我使用 Spring 注释构建 REST 服务。我有一个包含三个参数的 GET 请求,最后一个是电子邮件。
我的控制器:
@RequestMapping(method = GET, value = "/{value1}/{value2}/{value3:.+}",
produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
public ResponseEntity<MyResponseType> getMyResource(
@ApiParam(value = "...",...)
@PathVariable("value1") String value1,
@ApiParam(value = "...",...)
@PathVariable("value2") String value2,
@ApiParam(value = "...",...)
@PathVariable("value3") String value3) {
//...
}
如果我调用: http://myserver:8080/myresource/value1/value2/value3
用value3=email@domain.de/co.uk/.name/.biz/.info,完全没有问题。
但对于某些顶级域(目前为 .com、.org),我收到 Http 状态代码 406(未接受)。
如果我添加尾部斜杠,它会起作用:
http://myserver:8080/myresource/value1/value2/value3/
由于我们使用 swagger 并且 swagger 不添加尾部斜杠,因此添加尾部斜杠不是一个选项。
什么可能导致此问题?
我使用了一个扩展 ResponseEntityExceptionHandler 的 ErrorHandler。 我调试了一下,发现抛出了HttpMediaTypeNotAcceptableException ("Could not find acceptable representation")。但是我还不知道是谁扔的,为什么扔。
编辑
我发现路径 http://myserver:8080/myresource/value1/value2/myemail@somewhere.com
被解释为文件,而"com"是媒体类型"application/x-msdownload"的文件扩展名,所以在Spring的classProducesRequestCondition.ProduceMediaTypeExpression中"getMediaType().isCompatibleWith(acceptedMediaType)" 行的 matchMediaType 方法失败,因为实际生成的媒体类型是 "application/json;charset=UTF-8",而不是 "application/x-msdownload"。
所以问题变为:我怎样才能让 Spring 明白 .com 不是文件扩展名?
这个帖子帮助了我: SpringMVC: Inconsistent mapping behavior depending on url extension
显然这不是错误而是 "feature" 并且有两种不同的方法可以禁用它。我用的注释版本:
@Configuration
@EnableWebMvc
public class RestCommonsMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
我从 spring 3.1.2 升级到 3.2.7 时遇到了这个问题。 WebMvcConfigurerAdapter
,而是在我的 WebConfig
中扩展了 WebMvcConfigurationSupport
。
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
super.configureContentNegotiation(configurer);
configurer.favorPathExtension(false).favorParameter(true);
}
}