简体   繁体   中英

Getting 400 bad request error using POST while communicating to different domain

We have two projects for UI and server, both are running on different domains. For UI we are using angular JS and for server side we are using spring and providing the JSON responses to client. Because of CORS issue we are not able to communicate to server. We have googled it and tried different solutions. We found the below link.

https://htet101.wordpress.com/2014/01/22/cors-with-angularjs-and-spring-rest/

We did exactly whatever is mentioned in the link. It is working for GET requests but it is not working for POST request. When we do the POST request we are getting 400 Bad Request. Please check the below details for more information.

  1. Remote Address: IP:8080
  2. Request URL: http://IP:8080/controller/addLogin
  3. Request Method: POST
  4. Status Code: 400 Bad Request

Response Headers : HTTP/1.1 400 Bad Request Server: Apache-Coyote/1.1 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE Access-Control-Max-Age: 3600 Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept Content-Type: text/html;charset=utf-8 Content-Language: en Content-Length: 1113 Date: Mon, 28 Sep 2015 09:33:21 GMT Connection: close

Request Headers : POST /controller/addLogin HTTP/1.1 Host: 192.168.5.131:8080 Connection: keep-alive Content-Length: 41 Pragma: no-cache Cache-Control: no-cache Accept: application/json, text/plain, / Origin: localhost:1337 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Content-Type: application/json;charset=UTF-8 Referer: localhost:1337/login.html Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8

After getting this we added below lines at client side as we seen in some solutions in stacloverflow. But still the error remains same.

  $httpProvider.defaults.useXDomain = true;
  $httpProvider.defaults.withCredentials = true;
  $httpProvider.defaults.headers.common['Access-Control-Allow-Credentials'] = true;
  delete $httpProvider.defaults.headers.common["X-Requested-With"];
  $httpProvider.defaults.headers.post['Content-type'] = "application/json";

Please help us in solving this.

Updated Question :

We did the exact changes which are mentioned in below answer. Then we got exception like

 org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'corsFilter' is defined for enabling cors.

To resolve this we created bean

<bean id="corsFilter" class="com.prototype.helper.SimpleCORSFilter" /> 

in root-context.xml file. But still no luck for us, we are still getting 400 bad request like

POST http://IP Address:8080/controller/addLogin 400 (Bad Request).

Below is the filter class and web.xml configuration which we did :

public class SimpleCORSFilter extends OncePerRequestFilter {

 // private Set<String> whitelist = Sets.newHashSet("[AllowedOrigin1]", "[AllowedOrigin2]");

     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                     FilterChain filterChain) throws ServletException, IOException {

          String originHeaderFromClient = request.getHeader("Origin");
          response.setHeader("Access-Control-Allow-Origin", originHeaderFromClient);
          response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
          response.setHeader("Access-Control-Max-Age", "3600");
          response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
          filterChain.doFilter(request, response);
     }

}

web.xml:

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

If you inspect the network tab in developer options in your browser, you might see that the browser is making an OPTIONS call to the server before it makes a POST call.

Spring's DispatcherServlet blocks the OPTIONS call from entering your application by default. Meaning, the OPTIONS call will not go through. Your browser thinks that the server you are trying to reach doesn't support CORS and hence blocks the call from going through.

We implemented a Filter and wired it using DelegatingFilterProxy in web.xml like this:

<filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

And in the doFilter method of the Filter, did the following:

 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String originHeaderFromClient = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", <<acceptedOrigins>>;
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
        chain.doFilter(request, response);

This way, all calls will get the Access-Control-Allow-Origin header irrespective of GET/POST. And it also keeps the controllers clean of CORS header specific settings (which, if you have more than one controller is a pain).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM