title: Enabling Cross Origin Requests for WebSockets in Spring
body: <p>I have a OpenShift Wildfly server. I am building a website with the <code>Spring MVC</code> framework. One of my webpages also uses a WebSocket connection. On the server side, I have used the <code>@ServerEndpoint</code> annotation and <code>javax.websocket.*</code> library to create my websocket: </p>
  
  <pre><code>package com.myapp.spring.web.controller;
  import java.io.IOException;
  
  import javax.websocket.OnClose;
  import javax.websocket.OnError;
  import javax.websocket.OnMessage;
  import javax.websocket.OnOpen;
  import javax.websocket.Session;
  import javax.websocket.server.ServerEndpoint;
  
  import org.springframework.web.socket.server.standard.SpringConfigurator;
  
  
  @ServerEndpoint(value="/serverendpoint", configurator = SpringConfigurator.class)
  
  public class serverendpoint {
  
      @OnOpen
      public void handleOpen () {
          System.out.println("JAVA: Client is now connected...");
      }
  
      @OnMessage
      public String handleMessage (Session session, String message) throws IOException {
  
          if (message.equals("ping")) {
  //            return "pong"
                  session.getBasicRemote().sendText("pong");
          }
          else if (message.equals("close")) {
              handleClose();
              return null;
          }
          System.out.println("JAVA: Received from client: "+ message);
          MyClass mc = new MyClass(message);
          String res = mc.action();
          session.getBasicRemote().sendText(res);
          return res;
      }
  
      @OnClose
      public void handleClose() {
          System.out.println("JAVA: Client is now disconnected...");
      }
  
      @OnError
      public void handleError (Throwable t) {
          t.printStackTrace();
      }
  }
  </code></pre>
  
  <p>OpenShift gives a default URL, so all of my webpages (html files) have the common (canonical) hostname. For the sake of simplicity, I am calling this URL <code>URL A</code> (<strong><code>projectname-domainname.rhclound.com</code></strong>). I created an alias, CNAME, of <code>URL A</code>, which is called <code>URL B</code> (say <strong><code>https://www.mywebsite.tech</code></strong>). <code>URL B</code> is secure, as it has the <code>https</code>.</p>
  
  <p>I am using a JavaScript client to connect to the WebSocket at the path <code>/serverendpoint</code>. The URI I am using in my html webpage file, <code>test.html</code>, is the following: </p>
  
  <pre><code>var wsUri = "wss://" + "projectname-domainname.rhclound.com" + ":8443" + "/serverendpoint";
  </code></pre>
  
  <p>When I open up <code>URL A</code> (<strong><code>projectname-domainname.rhclound.com/test</code></strong>), the WebSocket connects and everything works fine. However, when I try to connect to the websocket using <code>URL B</code> (<strong><code>https://mywebsite.tech/test</code></strong>), the JavaScript client immediately connects and disconnects. </p>
  
  <p>Here is the message from the console that I receive:</p>
  
  <p><a href="https://i.stack.imgur.com/Y03zQ.png" rel="noreferrer"><img src="https://i.stack.imgur.com/Y03zQ.png" alt="enter image description here"></a></p>
  
  <p>Here is my JavaScript code that connects to the WebSocket:</p>
  
  <pre><code>/****** BEGIN WEBSOCKET ******/
              var connectedToWebSocket = false;
              var responseMessage = '';
              var webSocket = null;
              function initWS() {
                  connectedToWebSocket = false;
                  var wsUri = "wss://" + "projectname-domainname.rhcloud.com" + ":8443" + "/serverendpoint";
                  webSocket = new WebSocket(wsUri); // Create a new instance of WebSocket using usUri
                  webSocket.onopen = function(message) {
                      processOpen(message);
                  };
                  webSocket.onmessage = function(message) {
                      responseMessage = message.data;
                      if (responseMessage !== "pong") { // Ping-pong messages to keep a persistent connection between server and client
                          processResponse(responseMessage);
                      }
                      return false;
                  };
                  webSocket.onclose = function(message) {
                      processClose(message);
                  };
                  webSocket.onerror = function(message) {
                      processError(message);
                  };
                  console.log("Exiting initWS()");
              }
  
              initWS(); //Connect to websocket
  
              function processOpen(message) {
                  connectedToWebSocket = true;
                  console.log("JS: Server Connected..."+message);
              }
  
              function sendMessage(toServer) { // Send message to server
                  if (toServer != "close") {
                      webSocket.send(toServer);
                  } else {
                      webSocket.close();
                  }
              }
  
              function processClose(message) {
                  connectedToWebSocket = false;
                  console.log("JS: Client disconnected..."+message);
              }
  
              function processError(message) { 
                  userInfo("An error occurred. Please contact for assistance", true, true);
              }
              setInterval(function() {
                  if (connectedToWebSocket) {
                      webSocket.send("ping");
                  }
              }, 4000); // Send ping-pong message to server
  /****** END WEBSOCKET ******/
  </code></pre>
  
  <p>After a lot of debugging and trying various things, I concluded that this was problem was occurring because of the Spring Framework. <strong>This is because before I introduced the <code>Spring Framework</code> in my project, <code>URL B</code> could connect to the WebSocket, but after introducing Spring, it cannot.</strong><br>
  I read on <a href="http://docs.spring.io/spring-security/site/docs/current/reference/html/websocket.html" rel="noreferrer">spring's website</a> about WebSocket Policy. I came across their <a href="http://docs.spring.io/spring-security/site/docs/current/reference/html/websocket.html#websocket-sameorigin" rel="noreferrer">same origin policy</a> which states that an alias, <code>URL B</code>, cannot connect to the WebSocket because it is not the same origin as <code>URL A</code> is. To solve this problem I <a href="http://docs.spring.io/spring-security/site/docs/current/reference/html/websocket.html#websocket-sameorigin-disable" rel="noreferrer">disabled the same origin policy with WebSockets</a> as said in the documentation, so I added the following code. I thought that doing so would fix my error. Here is what I added:</p>
  
  <pre><code>import org.springframework.context.annotation.Configuration;
  import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
  
  @Configuration
  public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
  
      @Override
      protected boolean sameOriginDisabled() {
          return true;
      }
  
  }
  </code></pre>
  
  <p>However, this did not fix the problem, so I added the following method to my <code>ApplicationConfig</code> which <code>extends WebMvcConfigurerAdapter</code>: </p>
  
  <pre><code>@Override
  public void addCorsMappings(CorsRegistry registry) {
      registry.addMapping("/**").allowedOrigins("https://www.mywebsite.com");
  }
  </code></pre>
  
  <p>This also didn't work either. Then I tried this:</p>
  
  <pre><code>package com.myapp.spring.security.config;
  import org.springframework.boot.web.servlet.FilterRegistrationBean;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.web.cors.CorsConfiguration;
  import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  import org.springframework.web.filter.CorsFilter;
  
  @Configuration
  public class MyCorsFilter {
  
  //  @Bean
  //  public FilterRegistrationBean corsFilter() {
  //      System.out.println("Filchain");
  //      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  //      CorsConfiguration config = new CorsConfiguration();
  //      config.setAllowCredentials(true);
  //      config.addAllowedOrigin("https://www.mymt.tech");
  //      config.addAllowedHeader("*");
  //      config.addAllowedMethod("*");
  //      source.registerCorsConfiguration("/**", config);
  //      FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
  //      bean.setOrder(0);
  //      System.out.println("Filchain");
  //      return bean;
  //  }
  
       @Bean
       public CorsFilter corsFilter() {
           System.out.println("Filchain");
           UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
           CorsConfiguration config = new CorsConfiguration();
           config.setAllowCredentials(true); // you USUALLY want this
           config.addAllowedOrigin("*");
           config.addAllowedHeader("*");
           config.addAllowedMethod("*");
           config.addAllowedMethod("*");
           source.registerCorsConfiguration("/**", config);
           System.out.println("Filchain");
           return new CorsFilter(source);
       }
  
  }
  </code></pre>
  
  <p>This also did not work. </p>
  
  <p>I even changed the <code>var wsURI</code> in the JS code to the following: 
  <code>var wsUri = "wss://" + "www.mywebsite.com" + ":8443" + "/serverendpoint";</code>
  Then <code>var wsUri = "wss://" + "mywebsite.com" + ":8443" + "/serverendpoint";</code></p>
  
  <p>When I did this, the Google Chrome gave me an error, saying that the handshake failed. However, when I have this URL, <code>var wsUri = "wss://" + "projectname-domianname.rhcloud.com" + ":8443" + "/serverendpoint";</code>, I did not get the error that the handshake didn't occur, but I get a message that the connection opened and closed immediately (as seen above). </p>
  
  <p>So how can I fix this?</p>