获取 .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);
  }
}