/* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, version * 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.jboss.netty.handler.codec.http.websocketx; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; import org.jboss.netty.handler.codec.embedder.CodecEmbedderException; import org.jboss.netty.handler.codec.embedder.DecoderEmbedder; import org.jboss.netty.handler.codec.http.DefaultHttpRequest; import org.jboss.netty.handler.codec.http.HttpMethod; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpRequestDecoder; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseEncoder; import org.junit.Test; import java.util.LinkedList; import java.util.Queue; import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.*; import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*; import static org.jboss.netty.handler.codec.http.HttpVersion.*; import static org.junit.Assert.*; public class WebSocketServerProtocolHandlerTest { @Test public void testHttpUpgradeRequest() { DecoderEmbedder<Object> embedder = decoderEmbedder(); ChannelHandlerContext ctx = embedder.getPipeline().getContext(WebSocketServerProtocolHandshakeHandler.class); HttpResponseInterceptor responseInterceptor = addHttpResponseInterceptor(embedder); embedder.offer(WebSocketRequestBuilder.sucessful()); HttpResponse response = responseInterceptor.getHttpResponse(); assertEquals(SWITCHING_PROTOCOLS, response.getStatus()); assertNotNull(WebSocketServerProtocolHandler.getHandshaker(ctx)); } private static HttpResponseInterceptor addHttpResponseInterceptor(DecoderEmbedder<Object> embedder) { HttpResponseInterceptor interceptor = new HttpResponseInterceptor(); embedder.getPipeline().addLast("httpEncoder", interceptor); return interceptor; } @Test public void testSubsequentHttpRequestsAfterUpgradeShouldReturn403() throws Exception { DecoderEmbedder<Object> embedder = decoderEmbedder(); HttpResponseInterceptor responseInterceptor = addHttpResponseInterceptor(embedder); embedder.offer(WebSocketRequestBuilder.sucessful()); embedder.offer(new DefaultHttpRequest(HTTP_1_1, HttpMethod.GET, "path")); assertEquals(SWITCHING_PROTOCOLS, responseInterceptor.getHttpResponse().getStatus()); assertEquals(FORBIDDEN, responseInterceptor.getHttpResponse().getStatus()); } @Test public void testHttpUpgradeRequestInvalidUpgradeHeader() { DecoderEmbedder<Object> embedder = decoderEmbedder(); HttpRequest invalidUpgradeRequest = new WebSocketRequestBuilder().httpVersion(HTTP_1_1) .method(HttpMethod.GET) .uri("/test") .connection("Upgrade") .version00() .upgrade("BogusSocket") .build(); try { embedder.offer(invalidUpgradeRequest); } catch (Exception e) { assertWebSocketHandshakeException(e); } } @Test public void testHttpUpgradeRequestMissingWSKeyHeader() { DecoderEmbedder<Object> embedder = decoderEmbedder(); HttpRequest missingWSKeyRequest = new WebSocketRequestBuilder().httpVersion(HTTP_1_1) .method(HttpMethod.GET) .uri("/test") .key(null) .connection("Upgrade") .upgrade(WEBSOCKET.toLowerCase()) .version13() .build(); try { embedder.offer(missingWSKeyRequest); } catch (Exception e) { assertWebSocketHandshakeException(e); } } private static void assertWebSocketHandshakeException(Exception e) { assertTrue(e instanceof CodecEmbedderException); assertTrue(e.getCause() instanceof WebSocketHandshakeException); } @Test public void testHandleTextFrame() { CustomTextFrameHandler customTextFrameHandler = new CustomTextFrameHandler(); DecoderEmbedder<Object> embedder = decoderEmbedder(customTextFrameHandler); embedder.offer(WebSocketRequestBuilder.sucessful()); embedder.offer(new TextWebSocketFrame("payload")); assertEquals("processed: payload", customTextFrameHandler.getContent()); } private static DecoderEmbedder<Object> decoderEmbedder(SimpleChannelHandler handler) { DecoderEmbedder<Object> decoder = decoderEmbedder(); decoder.getPipeline().addFirst("someHandler", handler); return decoder; } private static DecoderEmbedder<Object> decoderEmbedder() { DecoderEmbedder<Object> decoder = new DecoderEmbedder<Object>( new HttpRequestDecoder(), new WebSocketServerProtocolHandler("path")); return decoder; } private static class CustomTextFrameHandler extends SimpleChannelHandler { private String content; @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (e.getMessage() instanceof TextWebSocketFrame) { TextWebSocketFrame frame = (TextWebSocketFrame) e.getMessage(); content = "processed: " + frame.getText(); } } public String getContent() { return content; } } private static class HttpResponseInterceptor extends HttpResponseEncoder { private final Queue<HttpResponse> responses = new LinkedList<HttpResponse>(); @Override protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { responses.add((HttpResponse) msg); return super.encode(ctx, channel, msg); } public HttpResponse getHttpResponse() { return responses.poll(); } } }