@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(); } }
public String getTransportType() { return transportType.name(); }