@Override
 protected boolean validateRequest(String serverId, String sessionId, String transport) {
   if (!getAllowedOrigins().contains("*")
       && !TransportType.fromValue(transport).supportsOrigin()) {
     logger.error("Origin check has been enabled, but this transport does not support it");
     return false;
   }
   return super.validateRequest(serverId, sessionId, transport);
 }
  /** Return the SockJS path or null if the path could not be determined. */
  private String getSockJsPath(ServerHttpRequest request) {

    String path = request.getURI().getPath();

    // SockJS prefix hints?
    if (!this.validSockJsPrefixes.isEmpty()) {
      for (String prefix : this.validSockJsPrefixes) {
        int index = path.indexOf(prefix);
        if (index != -1) {
          this.knownSockJsPrefixes.add(path.substring(0, index + prefix.length()));
          return path.substring(index + prefix.length());
        }
      }
      return null;
    }

    // SockJS info request?
    if (path.endsWith("/info")) {
      this.knownSockJsPrefixes.add(path.substring(0, path.length() - "/info".length()));
      return "/info";
    }

    // Have we seen this prefix before (following the initial /info request)?
    String match = null;
    for (String sockJsPath : this.knownSockJsPrefixes) {
      if (path.startsWith(sockJsPath)) {
        if ((match == null) || (match.length() < sockJsPath.length())) {
          match = sockJsPath;
        }
      }
    }
    if (match != null) {
      String result = path.substring(match.length());
      Assert.isTrue(
          result.charAt(0) == '/',
          "Invalid SockJS path extracted from incoming path \""
              + path
              + "\". The extracted SockJS path is \""
              + result
              + "\". It was extracted from these known SockJS prefixes "
              + this.knownSockJsPrefixes
              + ". Consider setting 'validSockJsPrefixes' on DefaultSockJsService.");
      return result;
    }

    // SockJS greeting?
    String pathNoSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
    String lastSegment = pathNoSlash.substring(pathNoSlash.lastIndexOf('/') + 1);

    if ((TransportType.fromValue(lastSegment) == null) && !lastSegment.startsWith("iframe")) {
      this.knownSockJsPrefixes.add(path);
      return "";
    }

    return null;
  }
  /** Return the SockJS path or null if the path could not be determined. */
  private String getSockJsPath(ServerHttpRequest request) {

    String path = request.getURI().getPath();

    // SockJS prefix hints?
    if (!this.sockJsPrefixes.isEmpty()) {
      for (String prefix : this.sockJsPrefixes) {
        int index = path.indexOf(prefix);
        if (index != -1) {
          this.sockJsPathCache.add(path.substring(0, index + prefix.length()));
          return path.substring(index + prefix.length());
        }
      }
      return null;
    }

    // SockJS info request?
    if (path.endsWith("/info")) {
      this.sockJsPathCache.add(path.substring(0, path.length() - 6));
      return "/info";
    }

    // Have we seen this prefix before (following the initial /info request)?
    String match = null;
    for (String sockJsPath : this.sockJsPathCache) {
      if (path.startsWith(sockJsPath)) {
        if ((match == null) || (match.length() < sockJsPath.length())) {
          match = sockJsPath;
        }
      }
    }
    if (match != null) {
      return path.substring(match.length());
    }

    // SockJS greeting?
    String pathNoSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
    String lastSegment = pathNoSlash.substring(pathNoSlash.lastIndexOf('/') + 1);

    if ((TransportType.fromValue(lastSegment) == null) && !lastSegment.startsWith("iframe")) {
      this.sockJsPathCache.add(path);
      return "";
    }

    return null;
  }
  @Override
  protected void handleTransportRequest(
      ServerHttpRequest request,
      ServerHttpResponse response,
      WebSocketHandler handler,
      String sessionId,
      String transport)
      throws SockJsException {

    TransportType transportType = TransportType.fromValue(transport);
    if (transportType == null) {
      logger.error("Unknown transport type for " + request.getURI());
      response.setStatusCode(HttpStatus.NOT_FOUND);
      return;
    }

    TransportHandler transportHandler = this.handlers.get(transportType);
    if (transportHandler == null) {
      logger.error("No TransportHandler for " + request.getURI());
      response.setStatusCode(HttpStatus.NOT_FOUND);
      return;
    }

    HttpMethod supportedMethod = transportType.getHttpMethod();
    if (!supportedMethod.equals(request.getMethod())) {
      if (HttpMethod.OPTIONS.equals(request.getMethod()) && transportType.supportsCors()) {
        if (checkAndAddCorsHeaders(request, response, HttpMethod.OPTIONS, supportedMethod)) {
          response.setStatusCode(HttpStatus.NO_CONTENT);
          addCacheHeaders(response);
        }
      } else if (transportType.supportsCors()) {
        sendMethodNotAllowed(response, supportedMethod, HttpMethod.OPTIONS);
      } else {
        sendMethodNotAllowed(response, supportedMethod);
      }
      return;
    }

    HandshakeInterceptorChain chain = new HandshakeInterceptorChain(this.interceptors, handler);
    SockJsException failure = null;

    try {
      SockJsSession session = this.sessions.get(sessionId);
      if (session == null) {
        if (transportHandler instanceof SockJsSessionFactory) {
          Map<String, Object> attributes = new HashMap<String, Object>();
          if (!chain.applyBeforeHandshake(request, response, attributes)) {
            return;
          }
          SockJsSessionFactory sessionFactory = (SockJsSessionFactory) transportHandler;
          session = createSockJsSession(sessionId, sessionFactory, handler, attributes);
        } else {
          response.setStatusCode(HttpStatus.NOT_FOUND);
          if (logger.isDebugEnabled()) {
            logger.debug(
                "Session not found, sessionId="
                    + sessionId
                    + ". The session may have been closed "
                    + "(e.g. missed heart-beat) while a message was coming in.");
          }
          return;
        }
      }

      if (transportType.sendsNoCacheInstruction()) {
        addNoCacheHeaders(response);
      }

      if (transportType.supportsCors()) {
        if (!checkAndAddCorsHeaders(request, response)) {
          return;
        }
      }

      transportHandler.handleRequest(request, response, handler, session);
      chain.applyAfterHandshake(request, response, null);
    } catch (SockJsException ex) {
      failure = ex;
    } catch (Throwable ex) {
      failure =
          new SockJsException("Uncaught failure for request " + request.getURI(), sessionId, ex);
    } finally {
      if (failure != null) {
        chain.applyAfterHandshake(request, response, failure);
        throw failure;
      }
    }
  }
  /**
   * TODO
   *
   * @param request
   * @param response
   * @param sockJsPath
   * @throws Exception
   */
  @Override
  public final void handleRequest(
      ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
      throws IOException, TransportErrorException {

    String sockJsPath = getSockJsPath(request);
    if (sockJsPath == null) {
      logger.warn(
          "Could not determine SockJS path for URL \""
              + request.getURI().getPath()
              + ". Consider setting validSockJsPrefixes.");
      response.setStatusCode(HttpStatus.NOT_FOUND);
      return;
    }

    logger.debug(request.getMethod() + " with SockJS path [" + sockJsPath + "]");

    try {
      request.getHeaders();
    } catch (IllegalArgumentException ex) {
      // Ignore invalid Content-Type (TODO)
    }

    try {
      if (sockJsPath.equals("") || sockJsPath.equals("/")) {
        response
            .getHeaders()
            .setContentType(new MediaType("text", "plain", Charset.forName("UTF-8")));
        response.getBody().write("Welcome to SockJS!\n".getBytes("UTF-8"));
        return;
      } else if (sockJsPath.equals("/info")) {
        this.infoHandler.handle(request, response);
        return;
      } else if (sockJsPath.matches("/iframe[0-9-.a-z_]*.html")) {
        this.iframeHandler.handle(request, response);
        return;
      } else if (sockJsPath.equals("/websocket")) {
        handleRawWebSocketRequest(request, response, handler);
        return;
      }

      String[] pathSegments = StringUtils.tokenizeToStringArray(sockJsPath.substring(1), "/");
      if (pathSegments.length != 3) {
        logger.warn("Expected \"/{server}/{session}/{transport}\" but got \"" + sockJsPath + "\"");
        response.setStatusCode(HttpStatus.NOT_FOUND);
        return;
      }

      String serverId = pathSegments[0];
      String sessionId = pathSegments[1];
      String transport = pathSegments[2];

      if (!validateRequest(serverId, sessionId, transport)) {
        response.setStatusCode(HttpStatus.NOT_FOUND);
        return;
      }

      handleTransportRequest(
          request, response, sessionId, TransportType.fromValue(transport), handler);
    } finally {
      response.flush();
    }
  }
Exemplo n.º 6
0
 public String getTransportType() {
   return transportType.name();
 }