post请求响应405,两种解决办法

问题

  • 为什么会出现405呢,一般是因为在发送POST请求时,请求路径写错,比如后端接口地址是/api/abc/ 而发送请求时的路径为/api/abc 没有了最后的斜线。

  • 这个问题一般通过后端做路径补全解决,如果要求前端每个都严格对上路径格式,那就太难为人了,增加无用工作量。

解决办法

  • 服务端解决有两种方法
  1. 应用服务器层面,通过应用服务器(如nginx)格式化路径;
  2. 应用层面,代码增加过滤器,格式化路径;

具体实现

  • 两种方法的实现
  1. 在nginx中可使用rewrite指令,在location中使用if判断uri结尾字符是否为斜杠,若不是,补充斜杠,具体实现代码如下:

    1
    2
    3
    4
    5
    6
    location /api/{
    if ($request_filename !~ "/$") {
    rewrite ^(/api/.*) $1/$args?;
    }
    proxy_pass http://127.0.0.1:8080;
    }
  2. 在应用层(Spring Web实现)增加过滤器,判断uri结尾,需要时补充斜杠,代码如下:

  • 定义过滤器逻辑:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    package default;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;

    /**
    * @author : championjing
    * @ClassName: UrlFilter
    * @Description: TODO
    * @Date: 3/1/2019 5:07 PM
    */
    public class UrlFilter implements Filter {
    private final static Logger LOGGER = LoggerFactory.getLogger(UrlFilter.class);

    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest)request;
    //HttpServletResponseWrapper httpResponse = new HttpServletResponseWrapper((HttpServletResponse) response);
    LOGGER.info("url:{}",httpRequest.getRequestURI());
    LOGGER.info("method:{}",httpRequest.getMethod());
    LOGGER.info("content_type:{}",httpRequest.getHeader("content-type"));
    LOGGER.info("cookie:{}",httpRequest.getHeader("cookie"));
    LOGGER.info("param:{}",httpRequest.getQueryString());
    String path=httpRequest.getRequestURI();
    if(!path.endsWith("/")){
    path=path+"/";
    LOGGER.info("格式化path:{}",path);
    httpRequest.getRequestDispatcher(path).forward(request,response);
    }
    else {
    chain.doFilter(request,response);

    }
    }

    @Override
    public void destroy() {

    }
    }
  • 向Spring容器中加入该过滤器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package default;

    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    /**
    * @author : championjing
    * @ClassName: FilterConfig
    * @Description: TODO
    * @Date: 3/1/2019 5:14 PM
    */
    @Configuration
    public class FilterConfig {
    @Bean
    public FilterRegistrationBean registFilter() {
    System.out.println("*******添加过滤器*******");
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new UrlFilter());
    registration.addUrlPatterns("/wx/*");
    registration.setName("UrlFilter");
    registration.setOrder(1);
    return registration;
    }
    }

小结

  • 当post一个并不存在接口时,会返回给405的响应,首先要检查路径是否写错,但极有可能是缺少斜杠问题,这种补全逻辑最好在服务端处理,减少前端失误,让我们一起呵护前端的小伙伴吧!
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2015-2020 AChampion
  • Powered by Hexo Theme Ayer
  • PV: UV:

开玩笑的~不用打赏