Merge branch 'jetty-7' into jetty-8

This commit is contained in:
Joakim Erdfelt 2013-02-21 17:34:19 -07:00
commit 95f166b374
4 changed files with 151 additions and 4 deletions

View File

@ -278,7 +278,7 @@ public class ProxyServletTest
"2\r\n"+
"YZ\r\n"+
"0\r\n"
).getBytes(StringUtil.__ISO_8859_1_CHARSET));
).getBytes(StringUtil.__ISO_8859_1));
String response=IO.toString(client.getInputStream());

View File

@ -230,6 +230,8 @@ public class WebSocketFactory extends AbstractLifeCycle
// Old pre-RFC version specifications (header not present in RFC-6455)
draft = request.getIntHeader("Sec-WebSocket-Draft");
}
// Remember requested version for possible error message later
int requestedVersion = draft;
AbstractHttpConnection http = AbstractHttpConnection.getCurrentConnection();
if (http instanceof BlockingHttpConnection)
throw new IllegalStateException("Websockets not supported on blocking connectors");
@ -252,7 +254,7 @@ public class WebSocketFactory extends AbstractLifeCycle
draft=Integer.MAX_VALUE;
switch (draft)
{
case -1: // unspecified draft/version
case -1: // unspecified draft/version (such as early OSX Safari 5.1 and iOS 5.x)
case 0: // Old school draft/version
{
connection = new WebSocketServletConnectionD00(this, websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
@ -283,7 +285,6 @@ public class WebSocketFactory extends AbstractLifeCycle
}
default:
{
LOG.warn("Unsupported Websocket version: " + draft);
// Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol
// Using the examples as outlined
String versions="13";
@ -295,7 +296,20 @@ public class WebSocketFactory extends AbstractLifeCycle
versions+=", 0";
response.setHeader("Sec-WebSocket-Version", versions);
throw new HttpException(400, "Unsupported websocket version specification: " + draft);
// Make error clear for developer / end-user
StringBuilder err = new StringBuilder();
err.append("Unsupported websocket client version specification ");
if(requestedVersion >= 0) {
err.append("[").append(requestedVersion).append("]");
} else {
err.append("<Unspecified, likely a pre-draft version of websocket>");
}
err.append(", configured minVersion [").append(_minVersion).append("]");
err.append(", reported supported versions [").append(versions).append("]");
LOG.warn(err.toString()); // Log it
// use spec language for unsupported versions
throw new HttpException(400, "Unsupported websocket version specification"); // Tell client
}
}

View File

@ -0,0 +1,119 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket;
import static org.hamcrest.Matchers.*;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.helper.CaptureSocket;
import org.eclipse.jetty.websocket.helper.SafariD00;
import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class WebSocketMinVersionTest
{
private Server server;
private WebSocketCaptureServlet servlet;
private URI serverUri;
@BeforeClass
public static void initLogging()
{
// Configure Logging
// System.setProperty("org.eclipse.jetty.util.log.class",StdErrLog.class.getName());
System.setProperty("org.eclipse.jetty.websocket.helper.LEVEL","DEBUG");
}
@Before
public void startServer() throws Exception
{
// Configure Server
server = new Server(0);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
// Serve capture servlet
servlet = new WebSocketCaptureServlet();
ServletHolder holder = new ServletHolder(servlet);
holder.setInitParameter("minVersion","8");
context.addServlet(holder,"/");
// Start Server
server.start();
Connector conn = server.getConnectors()[0];
String host = conn.getHost();
if (host == null)
{
host = "localhost";
}
int port = conn.getLocalPort();
serverUri = new URI(String.format("ws://%s:%d/",host,port));
// System.out.printf("Server URI: %s%n",serverUri);
}
@Test
public void testAttemptUpgrade() throws Exception
{
SafariD00 safari = new SafariD00(serverUri);
try
{
safari.connect();
safari.issueHandshake();
Assert.fail("Expected upgrade failure");
}
catch(IllegalStateException e) {
String respHeader = e.getMessage();
Assert.assertThat("Response Header", respHeader, allOf(
containsString("HTTP/1.1 400 Unsupported"),
containsString("minVersion [8]"),
containsString("[13, 8]")));
}
finally
{
// System.out.println("Closing client socket");
safari.disconnect();
}
}
public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException
{
long ms = TimeUnit.MILLISECONDS.convert(dur,unit);
Thread.sleep(ms);
}
@After
public void stopServer() throws Exception
{
server.stop();
}
}

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
@ -35,6 +36,7 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.Assert;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.is;
public class SafariD00
@ -109,12 +111,14 @@ public class SafariD00
// Read HTTP 101 Upgrade / Handshake Response
InputStreamReader reader = new InputStreamReader(in);
StringBuilder respHeaders = new StringBuilder();
LOG.debug("Reading http headers");
int crlfs = 0;
while (true)
{
int read = in.read();
respHeaders.append((char)read);
if (read == '\r' || read == '\n')
++crlfs;
else
@ -122,6 +126,16 @@ public class SafariD00
if (crlfs == 4)
break;
}
if(respHeaders.toString().startsWith("HTTP/1.1 101 ") == false) {
String respLine = respHeaders.toString();
int idx = respLine.indexOf('\r');
if(idx > 0) {
respLine = respLine.substring(0,idx);
}
LOG.debug("Response Headers: {}",respHeaders.toString());
throw new IllegalStateException(respLine);
}
// Read expected handshake hixie bytes
byte hixieHandshakeExpected[] = TypeUtil.fromHexString("c7438d956cf611a6af70603e6fa54809");