spring-Zuul / DispatcherServlet破坏了包含多部分的PUT请求(多部分数据已删除)

我们正在使用Zuul将请求转发到内部微服务.内部服务有2个端点(PUT端点和POST端点).我们发现多部分请求在到达我们的内部PUT端点之前已损坏.

多部分数据似乎已从请求中删除. PUT请求似乎只是这种情况,因为POST可以完美地工作.

如果我们直接使用cURL到达内部PUT端点,则该请求将被正确处理.相应的cURL命令和请求正文如下所示:

curl -v -X PUT -H "Content-Type: multipart/form-data" -F "file=@/path/to/file.txt" "http://localhost:8081/file/put"

Headers:

{user-agent=[curl/7.35.0], host=[localhost:8082], accept=[/], content-length=[203], expect=[100-continue], content-type=[multipart/form-data; boundary=————————c1efb86a9054e387]}

Entity:

————————–c1efb86a9054e387 Content-Disposition: form-data; name=”file”; filename=”helloworld.txt” Content-Type: text/plain

this is my file content

————————–c1efb86a9054e387–

但是,如果我们尝试通过Zuul使用cURL命中PUT端点,则请求如下所示:

curl -X PUT -H "Content-Type: multipart/form-data" -F "file=@/path/to/file.txt" "http://localhost:8082/file/put"

Header:

{user-agent=[curl/7.35.0], accept=[/], expect=[100-continue], content-type=[multipart/form-data;boundary=hkBnDNXOcDTwkuL1qLhglF6i4NA2YREd], x-forwarded-host=[localhost:8081], x-forwarded-proto=[http], x-forwarded-prefix=[/file], x-forwarded-port=[8081], x-forwarded-for=[127.0.0.1], accept-encoding=[gzip], content-length=[38], host=[localhost:8082], connection=[Keep-Alive]}

Entity:

–hkBnDNXOcDTwkuL1qLhglF6i4NA2YREd–

请注意,实体不完整.

我已将示例代码上传到此存储库:https://github.com/trcodestore/zuul-put-demo.该存储库包含2个用于演示此问题的小项目.自述文件包含构建和运行说明.

我知道请求最初由Spring的DispatcherServlet处理,然后最终由ZuulServlet处理.我相信是造成此问题的DispatcherServlet.我们可以通过为所有请求URI加上前缀“ / zuul”来绕开DispatcherServlet -这允许将多部分请求直接发送到ZuulServlet,然后按预期运行.但是,这不是理想的解决方案.

任何意见,将不胜感激.谢谢.

解决方法:

好的,我有解决方案(credit: Mohammad Zolmajd).

Spring Boot使用StandardServletMultipartResolver来处理多部分-假定所有多部分请求都将通过POST提交.

为了允许StandardServletMultipartResolver处理PUT请求,我们必须重写isMultiPart方法.我最终使用了以下配置:

@Bean
public MultipartResolver multipartResolver() {
   return new StandardServletMultipartResolver() {
     @Override
     public boolean isMultipart(HttpServletRequest request) {
        String method = request.getMethod().toLowerCase();
        if (!Arrays.asList("put", "post").contains(method)) {
           return false;
        }
        String contentType = request.getContentType();
        return (contentType != null &&contentType.toLowerCase().startsWith("multipart/"));
     }
   };
}
上一篇:Zuul【文件上传】


下一篇:.NET Core Web API使用HttpClient提交文件的二进制流(multipart/form-data内容类型)