Merge remote-tracking branch 'origin/master' into bug-359329
This commit is contained in:
commit
397aa79a50
|
@ -355,9 +355,8 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x//%s,g=%s,p=%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
return String.format("%s %s g=%s p=%s",
|
||||
super.toString(),
|
||||
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
|
||||
_generator,
|
||||
_parser);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -100,6 +99,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
};
|
||||
}
|
||||
};
|
||||
connector.setMaxIdleTime(2000);
|
||||
|
||||
// connector.setPort(5870);
|
||||
connector.setPort(0);
|
||||
|
@ -1181,6 +1181,54 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
closeClient(client);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testServerCloseClientDoesNotClose() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data, (byte)'Y');
|
||||
String content = new String(data, "UTF-8");
|
||||
automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertTrue(line.startsWith("HTTP/1.1 200 "));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
|
||||
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
|
||||
// TODO: timeout will not trigger.
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
|
||||
closeClient(client);
|
||||
}
|
||||
|
||||
private void assumeJavaVersionSupportsTLSRenegotiations()
|
||||
{
|
||||
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TimeoutTest
|
||||
{
|
||||
private static final Logger logger = Log.getLogger(TimeoutTest.class);
|
||||
private final AtomicInteger httpParses = new AtomicInteger();
|
||||
private ExecutorService threadPool;
|
||||
private Server server;
|
||||
private int serverPort;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
threadPool = Executors.newCachedThreadPool();
|
||||
server = new Server();
|
||||
|
||||
SelectChannelConnector connector = new SelectChannelConnector()
|
||||
{
|
||||
@Override
|
||||
protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint)
|
||||
{
|
||||
return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer())
|
||||
{
|
||||
@Override
|
||||
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
|
||||
{
|
||||
return new HttpParser(requestBuffers,endPoint,requestHandler)
|
||||
{
|
||||
@Override
|
||||
public int parseNext() throws IOException
|
||||
{
|
||||
System.out.print(".");
|
||||
httpParses.incrementAndGet();
|
||||
return super.parseNext();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
connector.setMaxIdleTime(2000);
|
||||
|
||||
// connector.setPort(5870);
|
||||
connector.setPort(0);
|
||||
|
||||
server.addConnector(connector);
|
||||
server.setHandler(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
if (contentLength != null)
|
||||
{
|
||||
int length = Integer.parseInt(contentLength);
|
||||
ServletInputStream input = request.getInputStream();
|
||||
for (int i = 0; i < length; ++i)
|
||||
input.read();
|
||||
}
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
serverPort = connector.getLocalPort();
|
||||
|
||||
logger.debug(" => :{}",serverPort);
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
if (server != null)
|
||||
server.stop();
|
||||
if (threadPool != null)
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
|
||||
private Socket newClient() throws IOException, InterruptedException
|
||||
{
|
||||
Socket client = new Socket("localhost",serverPort);
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that performs a seemingly normal http POST request, but with
|
||||
* a client that issues "connection: close", waits 100 seconds to
|
||||
* do anything with the connection (at all), and then attempts to
|
||||
* write a second POST request.
|
||||
* <p>
|
||||
* The connection should be closed by the server, and/or be closed
|
||||
* due to a timeout on the socket.
|
||||
*/
|
||||
@Ignore
|
||||
@Test
|
||||
public void testServerCloseClientDoesNotClose() throws Exception
|
||||
{
|
||||
// Log.getLogger("").setDebugEnabled(true);
|
||||
final Socket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data,(byte)'Y');
|
||||
String content = new String(data,"UTF-8");
|
||||
|
||||
// The request section
|
||||
StringBuilder req = new StringBuilder();
|
||||
req.append("POST / HTTP/1.1\r\n");
|
||||
req.append("Host: localhost\r\n");
|
||||
req.append("Content-Type: text/plain\r\n");
|
||||
req.append("Content-Length: ").append(content.length()).append("\r\n");
|
||||
req.append("Connection: close\r\n");
|
||||
req.append("\r\n");
|
||||
// and now, the POST content section.
|
||||
req.append(content);
|
||||
|
||||
// Send request to server
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
System.out.println("Client request #1 flushed");
|
||||
|
||||
InputStream in = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
in = client.getInputStream();
|
||||
isr = new InputStreamReader(in);
|
||||
reader = new BufferedReader(isr);
|
||||
|
||||
// Read the response header
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Got response header");
|
||||
|
||||
// Check that we did not spin
|
||||
int httpParseCount = httpParses.get();
|
||||
System.out.printf("Got %d http parses%n",httpParseCount);
|
||||
Assert.assertThat(httpParseCount,lessThan(50));
|
||||
|
||||
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
|
||||
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
|
||||
// TODO: timeout will not trigger.
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
|
||||
// Try to write another request (to prove that stream is closed)
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
Assert.fail("Should not have been able to send a second POST request (connection: close)");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(reader);
|
||||
IO.close(isr);
|
||||
IO.close(in);
|
||||
closeClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
private void closeClient(Socket client) throws IOException
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
|
@ -62,12 +62,6 @@ public abstract class AbstractConnection implements Connection
|
|||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x//%s:%d<->%s:%d",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_endp.getLocalAddr(),
|
||||
_endp.getLocalPort(),
|
||||
_endp.getRemoteAddr(),
|
||||
_endp.getRemotePort());
|
||||
return String.format("%s@%x", getClass().getSimpleName(), hashCode());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,7 +280,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
public void checkIdleTimestamp(long now)
|
||||
{
|
||||
long idleTimestamp=_idleTimestamp;
|
||||
|
||||
|
||||
if (idleTimestamp!=0 && _maxIdleTime>0)
|
||||
{
|
||||
long idleForMs=now-idleTimestamp;
|
||||
|
@ -709,24 +709,43 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
synchronized(this)
|
||||
// Do NOT use synchronized (this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
SelectionKey key = _key;
|
||||
String keyString = "";
|
||||
if (key != null)
|
||||
{
|
||||
return String.format("SCEP@%x{%s->%s,d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s%s%s}",
|
||||
hashCode(),
|
||||
_socket.getRemoteSocketAddress(),
|
||||
_socket.getLocalSocketAddress(),
|
||||
_dispatched,
|
||||
isOpen(),
|
||||
isInputShutdown(),
|
||||
isOutputShutdown(),
|
||||
_readBlocked,
|
||||
_writeBlocked,
|
||||
_writable,
|
||||
_interestOps,
|
||||
_key != null && _key.isValid() ? "" : "!",
|
||||
_key != null && _key.isValid() && _key.isReadable() ? "r" : "",
|
||||
_key != null && _key.isValid() && _key.isWritable() ? "w" : "");
|
||||
if (key.isValid())
|
||||
{
|
||||
if (key.isReadable())
|
||||
keyString += "r";
|
||||
if (key.isWritable())
|
||||
keyString += "w";
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString += "!";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString += "-";
|
||||
}
|
||||
return String.format("SCEP@%x{l(%s)<->r(%s),d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}",
|
||||
hashCode(),
|
||||
_socket.getRemoteSocketAddress(),
|
||||
_socket.getLocalSocketAddress(),
|
||||
_dispatched,
|
||||
isOpen(),
|
||||
isInputShutdown(),
|
||||
isOutputShutdown(),
|
||||
_readBlocked,
|
||||
_writeBlocked,
|
||||
_writable,
|
||||
_interestOps,
|
||||
keyString,
|
||||
_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -190,9 +190,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
_connection=next;
|
||||
progress=true;
|
||||
}
|
||||
// TODO: consider moving here hasProgressed() - it's only used in SSL
|
||||
}
|
||||
|
||||
LOG.debug("{} handle {} progress=",_session,this, progress);
|
||||
LOG.debug("{} handle {} progress={}", _session, this, progress);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -322,13 +323,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
case NOT_HANDSHAKING:
|
||||
{
|
||||
// Try wrapping some application data
|
||||
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
|
||||
progress=true;
|
||||
|
||||
// Try unwrapping some application data
|
||||
if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill))
|
||||
progress=true;
|
||||
|
||||
// Try wrapping some application data
|
||||
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
|
||||
progress=true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -389,6 +390,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
some_progress|=progress;
|
||||
}
|
||||
|
||||
if (toFill.hasContent())
|
||||
_aEndp.asyncDispatch();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -571,7 +575,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s | %s", super.toString(), _sslEndPoint);
|
||||
return String.format("%s %s", super.toString(), _sslEndPoint);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -628,7 +632,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
public int fill(Buffer buffer) throws IOException
|
||||
{
|
||||
int size=buffer.length();
|
||||
process(buffer,null);
|
||||
process(buffer, null);
|
||||
|
||||
int filled=buffer.length()-size;
|
||||
|
||||
|
@ -688,7 +692,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public void flush() throws IOException
|
||||
{
|
||||
process(null,null);
|
||||
process(null, null);
|
||||
}
|
||||
|
||||
public void asyncDispatch()
|
||||
|
@ -793,20 +797,20 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public String toString()
|
||||
{
|
||||
int i;
|
||||
int o;
|
||||
int u;
|
||||
synchronized(SslConnection.this)
|
||||
{
|
||||
i=_inbound==null?-1:_inbound.length();
|
||||
o=_outbound==null?-1:_outbound.length();
|
||||
u=_unwrapBuf==null?-1:_unwrapBuf.length();
|
||||
}
|
||||
return String.format("SSL:%s %s i/u/o=%d/%d/%d ishut=%b oshut=%b",
|
||||
_endp,
|
||||
// Do NOT use synchronized (SslConnection.this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
Buffer inbound = _inbound;
|
||||
Buffer outbound = _outbound;
|
||||
Buffer unwrap = _unwrapBuf;
|
||||
int i = inbound == null? -1 : inbound.length();
|
||||
int o = outbound == null ? -1 : outbound.length();
|
||||
int u = unwrap == null ? -1 : unwrap.length();
|
||||
return String.format("SSL %s i/o/u=%d/%d/%d ishut=%b oshut=%b {%s}",
|
||||
_engine.getHandshakeStatus(),
|
||||
i, u, o,
|
||||
_ishut, _oshut);
|
||||
i, o, u,
|
||||
_ishut, _oshut,
|
||||
_connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// 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
|
||||
// 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.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
|
|||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -56,14 +55,14 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
private static final String __version;
|
||||
static
|
||||
{
|
||||
if (Server.class.getPackage()!=null &&
|
||||
if (Server.class.getPackage()!=null &&
|
||||
"Eclipse.org - Jetty".equals(Server.class.getPackage().getImplementationVendor()) &&
|
||||
Server.class.getPackage().getImplementationVersion()!=null)
|
||||
__version=Server.class.getPackage().getImplementationVersion();
|
||||
else
|
||||
__version=System.getProperty("jetty.version","7.x.y-SNAPSHOT");
|
||||
}
|
||||
|
||||
|
||||
private final Container _container=new Container();
|
||||
private final AttributesMap _attributes = new AttributesMap();
|
||||
private ThreadPool _threadPool;
|
||||
|
@ -77,14 +76,14 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
private boolean _dumpAfterStart=false;
|
||||
private boolean _dumpBeforeStop=false;
|
||||
private boolean _uncheckedPrintWriter=false;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Server()
|
||||
{
|
||||
setServer(this);
|
||||
setServer(this);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience constructor
|
||||
* Creates server and a {@link SelectChannelConnector} at the passed port.
|
||||
|
@ -97,7 +96,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
connector.setPort(port);
|
||||
setConnectors(new Connector[]{connector});
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience constructor
|
||||
* Creates server and a {@link SelectChannelConnector} at the passed address.
|
||||
|
@ -118,7 +117,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return __version;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the container.
|
||||
|
@ -133,7 +132,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return _stopAtShutdown;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setStopAtShutdown(boolean stop)
|
||||
{
|
||||
|
@ -143,7 +142,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
else
|
||||
ShutdownThread.deregister(this);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the connectors.
|
||||
|
@ -161,7 +160,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
|
||||
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
|
||||
* remove a connector.
|
||||
* @param connector The connector to remove.
|
||||
*/
|
||||
|
@ -181,7 +180,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
for (int i=0;i<connectors.length;i++)
|
||||
connectors[i].setServer(this);
|
||||
}
|
||||
|
||||
|
||||
_container.update(this, _connectors, connectors, "connector");
|
||||
_connectors = connectors;
|
||||
}
|
||||
|
@ -194,7 +193,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return _threadPool;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param threadPool The threadPool to set.
|
||||
|
@ -240,32 +239,32 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
_dumpBeforeStop = dumpBeforeStop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
if (getStopAtShutdown())
|
||||
ShutdownThread.register(this);
|
||||
|
||||
|
||||
LOG.info("jetty-"+__version);
|
||||
HttpGenerator.setServerVersion(__version);
|
||||
MultiException mex=new MultiException();
|
||||
|
||||
|
||||
if (_threadPool==null)
|
||||
setThreadPool(new QueuedThreadPool());
|
||||
|
||||
try
|
||||
{
|
||||
super.doStart();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
super.doStart();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
mex.add(e);
|
||||
}
|
||||
|
||||
|
||||
if (_connectors!=null)
|
||||
{
|
||||
for (int i=0;i<_connectors.length;i++)
|
||||
|
@ -277,10 +276,10 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isDumpAfterStart())
|
||||
dumpStdErr();
|
||||
|
||||
|
||||
mex.ifExceptionThrow();
|
||||
}
|
||||
|
||||
|
@ -290,9 +289,9 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
if (isDumpBeforeStop())
|
||||
dumpStdErr();
|
||||
|
||||
|
||||
MultiException mex=new MultiException();
|
||||
|
||||
|
||||
if (_graceful>0)
|
||||
{
|
||||
if (_connectors!=null)
|
||||
|
@ -303,7 +302,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handler[] contexts = getChildHandlersByClass(Graceful.class);
|
||||
for (int c=0;c<contexts.length;c++)
|
||||
{
|
||||
|
@ -313,7 +312,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
Thread.sleep(_graceful);
|
||||
}
|
||||
|
||||
|
||||
if (_connectors!=null)
|
||||
{
|
||||
for (int i=_connectors.length;i-->0;)
|
||||
|
@ -321,7 +320,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
|
||||
|
||||
|
||||
mex.ifExceptionThrow();
|
||||
|
||||
if (getStopAtShutdown())
|
||||
|
@ -339,7 +338,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
final String target=connection.getRequest().getPathInfo();
|
||||
final Request request=connection.getRequest();
|
||||
final Response response=connection.getResponse();
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("REQUEST "+target+" on "+connection);
|
||||
|
@ -349,7 +348,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
else
|
||||
handle(target, request, request, response);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Handle a request from a connection.
|
||||
* Called to handle a request on the connection when either the header has been received,
|
||||
|
@ -378,7 +377,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
baseRequest.setRequestURI(null);
|
||||
baseRequest.setPathInfo(baseRequest.getRequestURI());
|
||||
if (uri.getQuery()!=null)
|
||||
baseRequest.mergeQueryString(uri.getQuery());
|
||||
baseRequest.mergeQueryString(uri.getQuery());
|
||||
}
|
||||
|
||||
final String target=baseRequest.getPathInfo();
|
||||
|
@ -395,10 +394,10 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
handle(target, baseRequest, request, response);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void join() throws InterruptedException
|
||||
public void join() throws InterruptedException
|
||||
{
|
||||
getThreadPool().join();
|
||||
}
|
||||
|
@ -490,8 +489,8 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
/**
|
||||
* Add an associated bean.
|
||||
* The bean will be added to the servers {@link Container}
|
||||
* and if it is a {@link LifeCycle} instance, it will be
|
||||
* started/stopped along with the Server. Any beans that are also
|
||||
* and if it is a {@link LifeCycle} instance, it will be
|
||||
* started/stopped along with the Server. Any beans that are also
|
||||
* {@link Destroyable}, will be destroyed with the server.
|
||||
* @param o the bean object to add
|
||||
*/
|
||||
|
@ -507,7 +506,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove a LifeCycle object to be started/stopped
|
||||
* Remove a LifeCycle object to be started/stopped
|
||||
* along with the Server
|
||||
* @deprecated Use {@link #removeBean(Object)}
|
||||
*/
|
||||
|
@ -516,7 +515,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
removeBean(c);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Remove an associated bean.
|
||||
|
@ -533,7 +532,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#clearAttributes()
|
||||
*/
|
||||
public void clearAttributes()
|
||||
|
@ -542,7 +541,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#getAttribute(java.lang.String)
|
||||
*/
|
||||
public Object getAttribute(String name)
|
||||
|
@ -551,7 +550,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#getAttributeNames()
|
||||
*/
|
||||
public Enumeration getAttributeNames()
|
||||
|
@ -560,7 +559,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#removeAttribute(java.lang.String)
|
||||
*/
|
||||
public void removeAttribute(String name)
|
||||
|
@ -569,7 +568,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#setAttribute(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void setAttribute(String name, Object attribute)
|
||||
|
@ -588,13 +587,13 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
|
||||
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
|
||||
* server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted
|
||||
* and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests
|
||||
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
|
||||
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
|
||||
* before stopping.
|
||||
* @param timeoutMS the milliseconds to wait for existing request to complete before stopping the server.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void setGracefulShutdown(int timeoutMS)
|
||||
{
|
||||
|
@ -613,7 +612,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
public void dump(Appendable out,String indent) throws IOException
|
||||
{
|
||||
dumpThis(out);
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
|
||||
}
|
||||
|
||||
|
||||
|
@ -629,7 +628,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
_uncheckedPrintWriter=unchecked;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* A handler that can be gracefully shutdown.
|
||||
* Called by doStop if a {@link #setGracefulShutdown} period is set.
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -29,14 +25,12 @@ import java.net.URL;
|
|||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Exchanger;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -44,6 +38,10 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -222,7 +220,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
// Read the response
|
||||
String response=readResponse(client);
|
||||
|
||||
|
||||
// Check the response
|
||||
assertEquals("response "+i,RESPONSE2,response);
|
||||
}
|
||||
|
@ -378,7 +376,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
try
|
||||
{
|
||||
URL url=new URL(_scheme+"://"+HOST+":"+_connector.getLocalPort()+"/?writes="+w+"&block="+b+ (e==0?"":("&encoding="+encoding[e]))+(c==0?"&chars=true":""));
|
||||
|
||||
|
||||
InputStream in = (InputStream)url.getContent();
|
||||
String response=IO.toString(in,e==0?null:encoding[e]);
|
||||
|
||||
|
@ -453,7 +451,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockingWhileWritingResponseContent() throws Exception
|
||||
{
|
||||
|
@ -521,7 +519,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
// read the chunked response header
|
||||
boolean chunked=false;
|
||||
boolean closed=false;
|
||||
|
@ -530,13 +528,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
String line=in.readLine();
|
||||
if (line==null || line.length()==0)
|
||||
break;
|
||||
|
||||
|
||||
chunked|="Transfer-Encoding: chunked".equals(line);
|
||||
closed|="Connection: close".equals(line);
|
||||
}
|
||||
Assert.assertTrue(chunked);
|
||||
Assert.assertFalse(closed);
|
||||
|
||||
|
||||
// Read the chunks
|
||||
int max=Integer.MIN_VALUE;
|
||||
while(true)
|
||||
|
@ -550,22 +548,22 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
if (max<len)
|
||||
max=len;
|
||||
}
|
||||
|
||||
|
||||
// Check that a direct content buffer was used as a chunk
|
||||
Assert.assertEquals(128*1024,max);
|
||||
|
||||
|
||||
// read and check the times are < 999ms
|
||||
String[] times=in.readLine().split(",");
|
||||
for (String t: times)
|
||||
Assert.assertTrue(Integer.valueOf(t).intValue()<999);
|
||||
|
||||
|
||||
|
||||
|
||||
// read the EOF chunk
|
||||
String end=in.readLine();
|
||||
Assert.assertEquals("0",end);
|
||||
end=in.readLine();
|
||||
Assert.assertEquals(0,end.length());
|
||||
|
||||
|
||||
|
||||
// read the non-chunked response header
|
||||
chunked=false;
|
||||
|
@ -575,13 +573,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
String line=in.readLine();
|
||||
if (line==null || line.length()==0)
|
||||
break;
|
||||
|
||||
|
||||
chunked|="Transfer-Encoding: chunked".equals(line);
|
||||
closed|="Connection: close".equals(line);
|
||||
}
|
||||
Assert.assertFalse(chunked);
|
||||
Assert.assertTrue(closed);
|
||||
|
||||
|
||||
String bigline = in.readLine();
|
||||
Assert.assertEquals(10*128*1024,bigline.length());
|
||||
|
||||
|
@ -589,7 +587,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
times=in.readLine().split(",");
|
||||
for (String t: times)
|
||||
Assert.assertTrue(t,Integer.valueOf(t).intValue()<999);
|
||||
|
||||
|
||||
// check close
|
||||
Assert.assertTrue(in.readLine()==null);
|
||||
}
|
||||
|
@ -607,7 +605,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
byte[] buf = new byte[128*1024];
|
||||
for (int i=0;i<buf.length;i++)
|
||||
buf[i]=(byte)("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(i%63));
|
||||
|
||||
|
||||
baseRequest.setHandled(true);
|
||||
response.setStatus(200);
|
||||
response.setContentType("text/plain");
|
||||
|
@ -631,7 +629,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPipeline() throws Exception
|
||||
|
@ -796,14 +794,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"content-length: 10\r\n"+
|
||||
"\015\012"+
|
||||
"123456789\n" +
|
||||
|
||||
|
||||
"HEAD /R1 HTTP/1.1\015\012"+
|
||||
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
|
||||
"content-type: text/plain; charset=utf-8\r\n"+
|
||||
"content-length: 10\r\n"+
|
||||
"\015\012"+
|
||||
"123456789\n"+
|
||||
|
||||
|
||||
"POST /R1 HTTP/1.1\015\012"+
|
||||
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
|
||||
"content-type: text/plain; charset=utf-8\r\n"+
|
||||
|
@ -811,25 +809,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"Connection: close\015\012"+
|
||||
"\015\012"+
|
||||
"123456789\n"
|
||||
|
||||
|
||||
).getBytes("iso-8859-1"));
|
||||
|
||||
|
||||
String in = IO.toString(is);
|
||||
|
||||
|
||||
int index=in.indexOf("123456789");
|
||||
assertTrue(index>0);
|
||||
index=in.indexOf("123456789",index+1);
|
||||
assertTrue(index>0);
|
||||
index=in.indexOf("123456789",index+1);
|
||||
assertTrue(index==-1);
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRecycledReaders() throws Exception
|
||||
{
|
||||
|
@ -909,27 +907,27 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"Connection: Keep-Alive\r\n"+
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
|
||||
|
||||
// Never send a body.
|
||||
// HelloWorldHandler does not read content, so 100 is not sent.
|
||||
// So close will have to happen anyway, without reset!
|
||||
|
||||
|
||||
os.flush();
|
||||
|
||||
|
||||
client.setSoTimeout(2000);
|
||||
long start=System.currentTimeMillis();
|
||||
String in = IO.toString(is);
|
||||
assertTrue(System.currentTimeMillis()-start<1000);
|
||||
assertTrue(in.indexOf("Connection: close")>0);
|
||||
assertTrue(in.indexOf("Hello world")>0);
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCommittedError() throws Exception
|
||||
{
|
||||
|
@ -950,25 +948,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
client.setSoTimeout(2000);
|
||||
String in = IO.toString(is);
|
||||
|
||||
assertEquals(-1,is.read()); // Closed by error!
|
||||
|
||||
|
||||
assertTrue(in.indexOf("HTTP/1.1 200 OK")>=0);
|
||||
assertTrue(in.indexOf("Transfer-Encoding: chunked")>0);
|
||||
assertTrue(in.indexOf("Now is the time for all good men to come to the aid of the party")>0);
|
||||
assertTrue(in.indexOf("\r\n0\r\n")==-1); // chunking is interrupted by error close
|
||||
|
||||
client.close();
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(100);
|
||||
assertTrue(!handler._endp.isOpen());
|
||||
}
|
||||
finally
|
||||
{
|
||||
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
|
||||
|
||||
|
||||
if (!client.isClosed())
|
||||
client.close();
|
||||
}
|
||||
|
@ -977,7 +975,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
protected static class CommittedErrorHandler extends AbstractHandler
|
||||
{
|
||||
public EndPoint _endp;
|
||||
|
||||
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
_endp=baseRequest.getConnection().getEndPoint();
|
||||
|
@ -987,15 +985,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
response.getWriter().println("Now is the time for all good men to come to the aid of the party");
|
||||
response.getWriter().flush();
|
||||
response.flushBuffer();
|
||||
|
||||
|
||||
throw new ServletException(new Exception("exception after commit"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class AvailableHandler extends AbstractHandler
|
||||
{
|
||||
public Exchanger<Object> _ex = new Exchanger<Object>();
|
||||
|
||||
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
|
@ -1003,31 +1001,31 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
response.setContentType("text/plain");
|
||||
InputStream in = request.getInputStream();
|
||||
ServletOutputStream out=response.getOutputStream();
|
||||
|
||||
|
||||
// should always be some input available, because of deferred dispatch.
|
||||
int avail=in.available();
|
||||
out.println(avail);
|
||||
|
||||
|
||||
String buf="";
|
||||
for (int i=0;i<avail;i++)
|
||||
buf+=(char)in.read();
|
||||
|
||||
|
||||
|
||||
avail=in.available();
|
||||
out.println(avail);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
_ex.exchange(null);
|
||||
_ex.exchange(null);
|
||||
_ex.exchange(null);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
avail=in.available();
|
||||
|
||||
|
||||
if (avail==0)
|
||||
{
|
||||
// handle blocking channel connectors
|
||||
|
@ -1047,15 +1045,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
for (int i=0;i<avail;i++)
|
||||
buf+=(char)in.read();
|
||||
|
||||
|
||||
avail=in.available();
|
||||
out.println(avail);
|
||||
out.println(buf);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testAvailable() throws Exception
|
||||
{
|
||||
|
@ -1082,7 +1080,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"1234567890"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
ah._ex.exchange(null);
|
||||
|
||||
os.write((
|
||||
|
@ -1091,7 +1089,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
os.flush();
|
||||
Thread.sleep(500);
|
||||
ah._ex.exchange(null);
|
||||
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
// skip header
|
||||
while(reader.readLine().length()>0);
|
||||
|
@ -1100,7 +1098,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
assertEquals(20,Integer.parseInt(reader.readLine()));
|
||||
assertEquals(0,Integer.parseInt(reader.readLine()));
|
||||
assertEquals("1234567890abcdefghijklmnopqrst",reader.readLine());
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -1108,7 +1106,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testDualRequest1() throws Exception
|
||||
{
|
||||
|
@ -1206,5 +1204,5 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -18,6 +16,9 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.junit.AfterClass;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
|
@ -91,11 +92,21 @@ public abstract class AbstractConnectHandlerTest
|
|||
StringBuilder body = new StringBuilder();
|
||||
if (headers.containsKey("content-length"))
|
||||
{
|
||||
int readLen = 0;
|
||||
int length = Integer.parseInt(headers.get("content-length"));
|
||||
for (int i = 0; i < length; ++i)
|
||||
try
|
||||
{
|
||||
char c = (char)reader.read();
|
||||
body.append(c);
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
char c = (char)reader.read();
|
||||
body.append(c);
|
||||
readLen++;
|
||||
}
|
||||
}
|
||||
catch (SocketTimeoutException e)
|
||||
{
|
||||
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n",readLen,length);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else if ("chunked".equals(headers.get("transfer-encoding")))
|
||||
|
@ -126,7 +137,7 @@ public abstract class AbstractConnectHandlerTest
|
|||
protected Socket newSocket() throws IOException
|
||||
{
|
||||
Socket socket = new Socket("localhost", proxyConnector.getLocalPort());
|
||||
socket.setSoTimeout(5000);
|
||||
socket.setSoTimeout(10000);
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,23 +14,17 @@
|
|||
|
||||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -38,6 +32,10 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @version $Revision$
|
||||
*/
|
||||
|
@ -122,22 +120,22 @@ public class ContextHandlerTest
|
|||
server.setConnectors(new Connector[] { connector });
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
|
||||
ContextHandler rootA = new ContextHandler(contexts,"/");
|
||||
ContextHandler fooA = new ContextHandler(contexts,"/foo");
|
||||
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
|
||||
|
||||
|
||||
server.start();
|
||||
|
||||
|
||||
// System.err.println(server.dump());
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob.jsp"));
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo/other"));
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,foobarA._scontext.getContext("/foo/bar"));
|
||||
|
@ -145,7 +143,7 @@ public class ContextHandlerTest
|
|||
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo/other"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testContextVirtualGetContext() throws Exception
|
||||
{
|
||||
|
@ -154,45 +152,45 @@ public class ContextHandlerTest
|
|||
server.setConnectors(new Connector[] { connector });
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
|
||||
ContextHandler rootA = new ContextHandler(contexts,"/");
|
||||
rootA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
ContextHandler rootB = new ContextHandler(contexts,"/");
|
||||
rootB.setVirtualHosts(new String[] {"b.com"});
|
||||
|
||||
|
||||
ContextHandler rootC = new ContextHandler(contexts,"/");
|
||||
rootC.setVirtualHosts(new String[] {"c.com"});
|
||||
|
||||
|
||||
|
||||
|
||||
ContextHandler fooA = new ContextHandler(contexts,"/foo");
|
||||
fooA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
ContextHandler fooB = new ContextHandler(contexts,"/foo");
|
||||
fooB.setVirtualHosts(new String[] {"b.com"});
|
||||
|
||||
|
||||
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
|
||||
foobarA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
server.start();
|
||||
|
||||
|
||||
// System.err.println(server.dump());
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob"));
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(rootB._scontext,rootB._scontext.getContext("/other"));
|
||||
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/other"));
|
||||
|
||||
|
||||
Assert.assertEquals(fooB._scontext,rootB._scontext.getContext("/foo/other"));
|
||||
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/foo/other"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testVirtualHostWildcard() throws Exception
|
||||
{
|
||||
|
@ -238,31 +236,31 @@ public class ContextHandlerTest
|
|||
ContextHandler context = new ContextHandler("/");
|
||||
|
||||
// test singular
|
||||
context.setVirtualHosts(new String[] { "www.example.com"} );
|
||||
context.setVirtualHosts(new String[] { "www.example.com"} );
|
||||
Assert.assertEquals(1,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test adding two more
|
||||
context.addVirtualHosts(new String[] { "www.example2.com", "www.example3.com"});
|
||||
Assert.assertEquals(3,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test adding existing context
|
||||
context.addVirtualHosts(new String[] { "www.example.com" });
|
||||
Assert.assertEquals(3,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing existing
|
||||
context.removeVirtualHosts(new String[] { "www.example3.com" });
|
||||
Assert.assertEquals(2,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing non-existent
|
||||
context.removeVirtualHosts(new String[] { "www.example3.com" });
|
||||
Assert.assertEquals(2,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing all remaining and resets to null
|
||||
context.removeVirtualHosts(new String[] { "www.example.com", "www.example2.com" });
|
||||
Assert.assertEquals(null,context.getVirtualHosts());
|
||||
|
||||
Assert.assertEquals(null,context.getVirtualHosts());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAttributes() throws Exception
|
||||
{
|
||||
|
@ -332,7 +330,7 @@ public class ContextHandlerTest
|
|||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUncheckedPrintWriter() throws Exception
|
||||
{
|
||||
|
@ -348,7 +346,7 @@ public class ContextHandlerTest
|
|||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
|
||||
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\n\n");
|
||||
|
||||
Assert.assertTrue(response.indexOf("Goodbye")>0);
|
||||
|
@ -401,7 +399,7 @@ public class ContextHandlerTest
|
|||
handled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class WriterHandler extends AbstractHandler
|
||||
{
|
||||
boolean error;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
|
||||
|
@ -25,7 +24,7 @@ import org.junit.runners.Parameterized.Parameters;
|
|||
|
||||
/**
|
||||
* Test the GzipFilter support for Content-Length setting variations.
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
|
@ -39,9 +38,9 @@ public class GzipFilterContentLengthTest
|
|||
* in different order so as to simulate the real world scenario
|
||||
* that caused the bug in Eclipse <a href="Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
* <p>
|
||||
* This test case will be run with each of the entries in
|
||||
* This test case will be run with each of the entries in
|
||||
* the array below as setup parameters for the test case.
|
||||
*
|
||||
*
|
||||
* @return the junit parameters
|
||||
*/
|
||||
@Parameters
|
||||
|
@ -49,7 +48,6 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
{ DefaultServlet.class },
|
||||
{ TestServletLengthStreamTypeWrite.class },
|
||||
{ TestServletLengthTypeStreamWrite.class },
|
||||
{ TestServletStreamLengthTypeWrite.class },
|
||||
|
@ -77,7 +75,7 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
|
||||
tester.prepareServerFile(filename,filesize);
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
@ -85,7 +83,7 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseGzipCompressed(filename);
|
||||
tester.assertIsResponseGzipCompressed(testfile.getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -97,7 +95,7 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
|
||||
tester.prepareServerFile(filename,filesize);
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
@ -105,7 +103,7 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed(filename,filesize,HttpStatus.OK_200);
|
||||
tester.assertIsResponseNotGzipCompressed(testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -119,7 +117,7 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedSmall() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",SMALL);
|
||||
assertIsGzipCompressed("file-small.txt",SMALL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +126,7 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedMedium() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",MEDIUM);
|
||||
assertIsGzipCompressed("file-med.txt",MEDIUM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,54 +135,54 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedLarge() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",LARGE);
|
||||
assertIsGzipCompressed("file-large.txt",LARGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedTiny() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.txt",TINY);
|
||||
assertIsNotGzipCompressed("file-tiny.txt",TINY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedSmall() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",SMALL);
|
||||
assertIsNotGzipCompressed("file-small.mp3",SMALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on medium size files
|
||||
* Tests for problems with Content-Length header on medium size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedMedium() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",MEDIUM);
|
||||
assertIsNotGzipCompressed("file-medium.mp3",MEDIUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on large size files
|
||||
* Tests for problems with Content-Length header on large size files
|
||||
* that were not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedLarge() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",LARGE);
|
||||
assertIsNotGzipCompressed("file-large.mp3",LARGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
@ -15,7 +12,6 @@ import java.util.Enumeration;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -30,6 +26,12 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GzipTester
|
||||
{
|
||||
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
|
||||
|
@ -41,7 +43,7 @@ public class GzipTester
|
|||
{
|
||||
this.testdir = testingdir;
|
||||
// Make sure we start with a clean testing directory.
|
||||
this.testdir.ensureEmpty();
|
||||
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
|
||||
}
|
||||
|
||||
public void assertIsResponseGzipCompressed(String filename) throws Exception
|
||||
|
@ -106,7 +108,7 @@ public class GzipTester
|
|||
* <p>
|
||||
* An example is to test that it is possible to configure GzipFilter to not recompress content that shouldn't be
|
||||
* compressed by the GzipFilter.
|
||||
*
|
||||
*
|
||||
* @param requestedFilename
|
||||
* the filename used to on the GET request,.
|
||||
* @param testResourceSha1Sum
|
||||
|
@ -189,7 +191,7 @@ public class GzipTester
|
|||
/**
|
||||
* Asserts that the requested filename results in a properly structured GzipFilter response, where the content is
|
||||
* not compressed, and the content-length is returned appropriately.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* the filename used for the request, and also used to compare the response to the server file, assumes
|
||||
* that the file is suitable for {@link Assert#assertEquals(Object, Object)} use. (in other words, the
|
||||
|
@ -230,7 +232,7 @@ public class GzipTester
|
|||
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
|
||||
|
||||
|
||||
// Assert that the contents are what we expect.
|
||||
if (filename != null)
|
||||
{
|
||||
|
@ -256,13 +258,13 @@ public class GzipTester
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate string content of arbitrary length.
|
||||
*
|
||||
*
|
||||
* @param length
|
||||
* the length of the string to generate.
|
||||
* @return the string content.
|
||||
|
@ -303,37 +305,42 @@ public class GzipTester
|
|||
|
||||
/**
|
||||
* Create a file on the server resource path of a specified filename and size.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* the filename to create
|
||||
* @param filesize
|
||||
* the file size to create (Note: this isn't suitable for creating large multi-megabyte files)
|
||||
*/
|
||||
public void prepareServerFile(String filename, int filesize) throws IOException
|
||||
public File prepareServerFile(String filename, int filesize) throws IOException
|
||||
{
|
||||
File testFile = testdir.getFile(filename);
|
||||
File dir = testdir.getDir();
|
||||
File testFile = new File(dir,filename);
|
||||
// Make sure we have a uniq filename (to work around windows File.delete bug)
|
||||
int i = 0;
|
||||
while (testFile.exists())
|
||||
{
|
||||
testFile = new File(dir,(i++) + "-" + filename);
|
||||
}
|
||||
|
||||
FileOutputStream fos = null;
|
||||
BufferedOutputStream out = null;
|
||||
ByteArrayInputStream in = null;
|
||||
try
|
||||
{
|
||||
fos = new FileOutputStream(testFile,false);
|
||||
out = new BufferedOutputStream(fos);
|
||||
in = new ByteArrayInputStream(generateContent(filesize).getBytes(encoding));
|
||||
IO.copy(in,out);
|
||||
IO.copy(in,fos);
|
||||
return testFile;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(in);
|
||||
IO.close(out);
|
||||
IO.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy a src/test/resource file into the server tree for eventual serving.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* the filename to look for in src/test/resources
|
||||
*/
|
||||
|
@ -341,13 +348,13 @@ public class GzipTester
|
|||
{
|
||||
File srcFile = MavenTestingUtils.getTestResourceFile(filename);
|
||||
File testFile = testdir.getFile(filename);
|
||||
|
||||
|
||||
IO.copy(srcFile,testFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servlet that provides content for the GzipFilter in being tested.
|
||||
*
|
||||
*
|
||||
* @param servletClass
|
||||
* the servlet that will provide content.
|
||||
* @return the FilterHolder for configuring the GzipFilter's initParameters with
|
||||
|
|
|
@ -141,7 +141,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the shared mask generator, or null if no shared mask generator is used
|
||||
* @see {@link WebSocketClient#getMaskGen()}
|
||||
* @see WebSocketClient#getMaskGen()
|
||||
*/
|
||||
public MaskGen getMaskGen()
|
||||
{
|
||||
|
@ -151,7 +151,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param maskGen the shared mask generator, or null if no shared mask generator is used
|
||||
* @see {@link WebSocketClient#setMaskGen(MaskGen)}
|
||||
* @see WebSocketClient#setMaskGen(MaskGen)
|
||||
*/
|
||||
public void setMaskGen(MaskGen maskGen)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
|
||||
|
@ -14,8 +10,6 @@ public interface WebSocketConnection extends AsyncConnection
|
|||
{
|
||||
void fillBuffersFrom(Buffer buffer);
|
||||
|
||||
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
|
||||
|
||||
List<Extension> getExtensions();
|
||||
|
||||
WebSocket.Connection getConnection();
|
||||
|
|
|
@ -19,10 +19,6 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -30,7 +26,6 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
|
|||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -43,13 +38,13 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
public final static byte LENGTH_FRAME=(byte)0x80;
|
||||
public final static byte SENTINEL_FRAME=(byte)0x00;
|
||||
|
||||
final WebSocketParser _parser;
|
||||
final WebSocketGenerator _generator;
|
||||
final WebSocket _websocket;
|
||||
final String _protocol;
|
||||
String _key1;
|
||||
String _key2;
|
||||
ByteArrayBuffer _hixieBytes;
|
||||
private final WebSocketParser _parser;
|
||||
private final WebSocketGenerator _generator;
|
||||
private final WebSocket _websocket;
|
||||
private final String _protocol;
|
||||
private String _key1;
|
||||
private String _key2;
|
||||
private ByteArrayBuffer _hixieBytes;
|
||||
|
||||
public WebSocketConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
|
@ -340,54 +335,6 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri=request.getRequestURI();
|
||||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
uri=new HttpURI(uri).toString();
|
||||
String host=request.getHeader("Host");
|
||||
|
||||
String origin=request.getHeader("Sec-WebSocket-Origin");
|
||||
if (origin==null)
|
||||
origin=request.getHeader("Origin");
|
||||
if (origin!=null)
|
||||
origin= QuotedStringTokenizer.quoteIfNeeded(origin, "\r\n");
|
||||
|
||||
|
||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||
|
||||
if (key1!=null)
|
||||
{
|
||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||
setHixieKeys(key1,key2);
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
if (origin!=null)
|
||||
response.addHeader("Sec-WebSocket-Origin",origin);
|
||||
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101,"WebSocket Protocol Handshake");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("WebSocket-Origin",origin);
|
||||
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101,"Web Socket Protocol Handshake");
|
||||
response.flushBuffer();
|
||||
if (_websocket instanceof OnFrame)
|
||||
((OnFrame)_websocket).onHandshake(this);
|
||||
_websocket.onOpen(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxTextMessageSize(int size)
|
||||
{
|
||||
}
|
||||
|
@ -427,6 +374,19 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_websocket instanceof OnFrame)
|
||||
{
|
||||
((OnFrame)_websocket).onHandshake(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebsocketOpen()
|
||||
{
|
||||
_websocket.onOpen(this);
|
||||
}
|
||||
|
||||
static class FrameHandlerD00 implements WebSocketParser.FrameHandler
|
||||
{
|
||||
|
|
|
@ -19,9 +19,6 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -73,7 +70,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final WebSocketParser _parser;
|
||||
private final WebSocketGenerator _generator;
|
||||
|
@ -101,10 +97,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new FrameHandlerD06();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
private final WebSocket.FrameConnection _connection = new FrameConnectionD06();
|
||||
|
||||
|
||||
|
@ -287,9 +279,20 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame!=null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
private class FrameConnectionD06 implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -487,6 +490,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getSimpleName()+"@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
|
||||
|
@ -693,29 +697,13 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
_connection.close(code,message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return WebSocketConnectionD06.this.toString()+"FH";
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
{
|
||||
|
|
|
@ -19,16 +19,12 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
@ -110,7 +106,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
|
||||
|
||||
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
|
||||
|
||||
|
||||
|
@ -375,8 +370,19 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame != null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private class WSFrameConnection implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -799,27 +805,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade", "WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
{
|
||||
|
@ -840,6 +825,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WS/D"+_draft+"-"+_endp;
|
||||
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,16 +19,12 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8Appendable;
|
||||
|
@ -397,8 +393,19 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame != null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private class WSFrameConnection implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -916,27 +923,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
return WebSocketConnectionD13.this.toString()+"FH";
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
|
@ -958,6 +944,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WS/D"+_draft+"-"+_endp;
|
||||
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -201,40 +200,43 @@ public class WebSocketFactory
|
|||
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
|
||||
|
||||
List<String> extensions_requested = new ArrayList<String>();
|
||||
for (Enumeration e=request.getHeaders("Sec-WebSocket-Extensions");e.hasMoreElements();)
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
QuotedStringTokenizer tok = new QuotedStringTokenizer((String)e.nextElement(),",");
|
||||
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
|
||||
while (tok.hasMoreTokens())
|
||||
{
|
||||
extensions_requested.add(tok.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final WebSocketConnection connection;
|
||||
final WebSocketServletConnection connection;
|
||||
final List<Extension> extensions;
|
||||
switch (draft)
|
||||
{
|
||||
case -1:
|
||||
case 0:
|
||||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
connection = new WebSocketServletConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 6:
|
||||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
connection = new WebSocketServletConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD08.OP_EXT_DATA, 16-WebSocketConnectionD08.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
connection = new WebSocketServletConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
case 13:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
connection = new WebSocketServletConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unsupported Websocket version: "+draft);
|
||||
|
@ -292,7 +294,8 @@ public class WebSocketFactory
|
|||
|
||||
// Try each requested protocol
|
||||
WebSocket websocket = null;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
|
||||
String protocol=null;
|
||||
while (protocol==null && protocols!=null && protocols.hasMoreElements())
|
||||
|
@ -314,7 +317,7 @@ public class WebSocketFactory
|
|||
{
|
||||
// Try with no protocol
|
||||
websocket = _acceptor.doWebSocketConnect(request, null);
|
||||
|
||||
|
||||
if (websocket==null)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
|
|
@ -65,7 +65,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
throw new EofException("Closed");
|
||||
if (opcode==WebSocketConnectionD13.OP_CLOSE)
|
||||
_closed=true;
|
||||
|
||||
|
||||
boolean mask=_maskGen!=null;
|
||||
|
||||
if (_buffer==null)
|
||||
|
@ -240,4 +240,17 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
// Do NOT use synchronized (this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
Buffer buffer = _buffer;
|
||||
return String.format("%s@%x closed=%b buffer=%d",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_closed,
|
||||
buffer == null ? -1 : buffer.length());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
{
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getBuffer();
|
||||
|
||||
|
||||
boolean progress=false;
|
||||
int filled=-1;
|
||||
|
||||
|
@ -189,7 +189,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
// Did we get enough?
|
||||
if (available<(_state==State.SKIP?1:_bytesNeeded))
|
||||
break;
|
||||
|
||||
|
||||
// if we are here, then we have sufficient bytes to process the current state.
|
||||
// Parse the buffer byte by byte (unless it is STATE_DATA)
|
||||
byte b;
|
||||
|
@ -307,7 +307,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
if (_bytesNeeded==0)
|
||||
_state=State.START;
|
||||
break;
|
||||
|
||||
|
||||
case SEEK_EOF:
|
||||
progress=true;
|
||||
_buffer.skip(available);
|
||||
|
@ -349,7 +349,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return progress?1:filled;
|
||||
}
|
||||
|
||||
|
@ -380,8 +380,10 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
Buffer buffer=_buffer;
|
||||
return WebSocketParserD13.class.getSimpleName()+"@"+ Integer.toHexString(hashCode())+"|"+_state+"|"+(buffer==null?"<>":buffer.toDetailString());
|
||||
return String.format("%s@%x state=%s buffer=%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_state,
|
||||
_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,17 +4,16 @@
|
|||
// 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
|
||||
// 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.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -39,12 +38,13 @@ import javax.servlet.http.HttpServletResponse;
|
|||
* <p>
|
||||
* The initParameter "maxBinaryMessagesSize" can be used to set the size in bytes
|
||||
* that a websocket may be accept before closing.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class WebSocketServlet extends HttpServlet implements WebSocketFactory.Acceptor
|
||||
{
|
||||
WebSocketFactory _webSocketFactory;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.GenericServlet#init()
|
||||
|
@ -57,15 +57,15 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
String max=getInitParameter("maxIdleTime");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxIdleTime(Integer.parseInt(max));
|
||||
|
||||
|
||||
max=getInitParameter("maxTextMessageSize");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxTextMessageSize(Integer.parseInt(max));
|
||||
|
||||
|
||||
max=getInitParameter("maxBinaryMessageSize");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxBinaryMessageSize(Integer.parseInt(max));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -74,7 +74,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
*/
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
{
|
||||
if (_webSocketFactory.acceptWebSocket(request,response) || response.isCommitted())
|
||||
return;
|
||||
super.service(request,response);
|
||||
|
@ -85,7 +85,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public interface WebSocketServletConnection extends WebSocketConnection
|
||||
{
|
||||
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
|
||||
public class WebSocketServletConnectionD00 extends WebSocketConnectionD00 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
|
||||
}
|
||||
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri = request.getRequestURI();
|
||||
String query = request.getQueryString();
|
||||
if (query != null && query.length() > 0)
|
||||
{
|
||||
uri += "?" + query;
|
||||
}
|
||||
uri = new HttpURI(uri).toString();
|
||||
String host = request.getHeader("Host");
|
||||
|
||||
String origin = request.getHeader("Sec-WebSocket-Origin");
|
||||
if (origin == null)
|
||||
{
|
||||
origin = request.getHeader("Origin");
|
||||
}
|
||||
if (origin != null)
|
||||
{
|
||||
origin = QuotedStringTokenizer.quoteIfNeeded(origin,"\r\n");
|
||||
}
|
||||
|
||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||
|
||||
if (key1 != null)
|
||||
{
|
||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||
setHixieKeys(key1,key2);
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
if (origin != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Origin",origin);
|
||||
}
|
||||
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
response.sendError(101,"WebSocket Protocol Handshake");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("WebSocket-Origin",origin);
|
||||
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
response.sendError(101,"Web Socket Protocol Handshake");
|
||||
response.flushBuffer();
|
||||
|
||||
onFrameHandshake();
|
||||
onWebsocketOpen();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD06 extends WebSocketConnectionD06 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD06(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD08 extends WebSocketConnectionD08 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
|
||||
}
|
||||
|
||||
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
for (Extension ext : getExtensions())
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD13 extends WebSocketConnectionD13 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
|
||||
}
|
||||
|
||||
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
for (Extension ext : getExtensions())
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue