parent
4527ba1801
commit
3d93d39b39
|
@ -45,15 +45,19 @@ public class FileServer
|
|||
// In this example it is the current directory but it can be configured to anything that the jvm has access to.
|
||||
resource_handler.setDirectoriesListed(true);
|
||||
resource_handler.setWelcomeFiles(new String[]{ "index.html" });
|
||||
resource_handler.setResourceBase(".");
|
||||
resource_handler.setResourceBase("/tmp/docroot");
|
||||
|
||||
// Add the ResourceHandler to the server.
|
||||
GzipHandler gzip = new GzipHandler();
|
||||
server.setHandler(gzip);
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
|
||||
server.setHandler(handlers);
|
||||
|
||||
/*
|
||||
GzipHandler gzip = new GzipHandler();
|
||||
server.setHandler(gzip);
|
||||
gzip.setHandler(handlers);
|
||||
|
||||
*/
|
||||
|
||||
// Start things up! By using the server.join() the server thread will join with the current thread.
|
||||
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
|
||||
server.start();
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package org.eclipse.jetty.embedded;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class SlowGet
|
||||
{
|
||||
public static void main(String... args) throws Exception
|
||||
{
|
||||
try(Socket socket = new Socket("localhost",8080))
|
||||
{
|
||||
socket.getOutputStream().write("GET /data.txt HTTP/1.0\r\n\r\n".getBytes());
|
||||
socket.getOutputStream().flush();
|
||||
|
||||
InputStream in = socket.getInputStream();
|
||||
byte[] headers = new byte[1024];
|
||||
int len = in.read(headers);
|
||||
|
||||
System.err.println("read="+len);
|
||||
|
||||
int b=0;
|
||||
while (b>=0)
|
||||
{
|
||||
b = in.read();
|
||||
if ((++len % 1024)==0)
|
||||
System.err.println("read="+(++len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
|
@ -71,6 +71,18 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
return _expect100Continue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdleTimeout(long timeoutMs)
|
||||
{
|
||||
getStream().setIdleTimeout(timeoutMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return getStream().getIdleTimeout();
|
||||
}
|
||||
|
||||
public Runnable onRequest(HeadersFrame frame)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.net.Socket;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ByteChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -168,6 +170,7 @@ public class ChannelEndPoint extends AbstractEndPoint
|
|||
@Override
|
||||
public boolean flush(ByteBuffer... buffers) throws IOException
|
||||
{
|
||||
System.err.println("FLUSH: "+Arrays.stream(buffers).map(b->BufferUtil.toDetailString(b)).collect(Collectors.toList()));
|
||||
long flushed=0;
|
||||
try
|
||||
{
|
||||
|
|
|
@ -80,6 +80,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
private final Response _response;
|
||||
private MetaData.Response _committedMetaData;
|
||||
private RequestLog _requestLog;
|
||||
private long _oldIdleTimeout;
|
||||
|
||||
/** Bytes written after interception (eg after compression) */
|
||||
private long _written;
|
||||
|
@ -596,6 +597,11 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
if (_configuration.getSendDateHeader() && !fields.contains(HttpHeader.DATE))
|
||||
fields.put(_connector.getServer().getDateField());
|
||||
|
||||
long idleTO=_configuration.getIdleTimeout();
|
||||
_oldIdleTimeout=getIdleTimeout();
|
||||
if (idleTO>=0 && _oldIdleTimeout!=idleTO)
|
||||
setIdleTimeout(idleTO);
|
||||
|
||||
_request.setMetaData(request);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -627,6 +633,10 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
if (_requestLog!=null )
|
||||
_requestLog.log(_request, _response);
|
||||
|
||||
long idleTO=_configuration.getIdleTimeout();
|
||||
if (idleTO>=0 && getIdleTimeout()!=_oldIdleTimeout)
|
||||
setIdleTimeout(_oldIdleTimeout);
|
||||
|
||||
_transport.onCompleted();
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public class HttpConfiguration
|
|||
private int _responseHeaderSize=8*1024;
|
||||
private int _headerCacheSize=512;
|
||||
private int _securePort;
|
||||
private long _idleTimeout=-1;
|
||||
private long _blockingTimeout=-1;
|
||||
private String _secureScheme = HttpScheme.HTTPS.asString();
|
||||
private boolean _sendServerVersion = true;
|
||||
|
@ -64,6 +65,7 @@ public class HttpConfiguration
|
|||
private boolean _delayDispatchUntilContent = true;
|
||||
private boolean _persistentConnectionsEnabled = true;
|
||||
private int _maxErrorDispatches = 10;
|
||||
private int _minRequestDataRate;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -113,6 +115,7 @@ public class HttpConfiguration
|
|||
_headerCacheSize=config._headerCacheSize;
|
||||
_secureScheme=config._secureScheme;
|
||||
_securePort=config._securePort;
|
||||
_idleTimeout=config._idleTimeout;
|
||||
_blockingTimeout=config._blockingTimeout;
|
||||
_sendDateHeader=config._sendDateHeader;
|
||||
_sendServerVersion=config._sendServerVersion;
|
||||
|
@ -206,6 +209,31 @@ public class HttpConfiguration
|
|||
return _persistentConnectionsEnabled;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the max idle time in ms.
|
||||
* <p>The max idle time is applied to a HTTP request for IO operations and
|
||||
* delayed dispatch.
|
||||
* @return the max idle time in ms or if == 0 implies an infinite timeout, <0
|
||||
* implies no HTTP channel timeout and the connection timeout is used instead.
|
||||
*/
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return _idleTimeout;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the max idle time in ms.
|
||||
* <p>The max idle time is applied to a HTTP request for IO operations and
|
||||
* delayed dispatch.
|
||||
* @param timeoutMs the max idle time in ms or if == 0 implies an infinite timeout, <0
|
||||
* implies no HTTP channel timeout and the connection timeout is used instead.
|
||||
*/
|
||||
public void setIdleTimeout(long timeoutMs)
|
||||
{
|
||||
_idleTimeout=timeoutMs;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the timeout applied to blocking operations.
|
||||
* <p>This timeout is in addition to the {@link Connector#getIdleTimeout()}, and applies
|
||||
|
@ -479,4 +507,22 @@ public class HttpConfiguration
|
|||
{
|
||||
_maxErrorDispatches=max;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return The minimum request data rate in bytes per second; or <=0 for no limit
|
||||
*/
|
||||
public int getMinRequestDataRate()
|
||||
{
|
||||
return _minRequestDataRate;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param bytesPerSecond The minimum request data rate in bytes per second; or <=0 for no limit
|
||||
*/
|
||||
public void setMinRequestDataRate(int bytesPerSecond)
|
||||
{
|
||||
_minRequestDataRate=bytesPerSecond;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ public class HttpInput extends ServletInputStream implements Runnable
|
|||
private final HttpChannelState _channelState;
|
||||
private ReadListener _listener;
|
||||
private State _state = STREAM;
|
||||
private long _contentArrived;
|
||||
private long _contentConsumed;
|
||||
private long _blockingTimeoutAt = -1;
|
||||
|
||||
|
@ -83,6 +84,7 @@ public class HttpInput extends ServletInputStream implements Runnable
|
|||
}
|
||||
_listener = null;
|
||||
_state = STREAM;
|
||||
_contentArrived = 0;
|
||||
_contentConsumed = 0;
|
||||
}
|
||||
}
|
||||
|
@ -139,9 +141,23 @@ public class HttpInput extends ServletInputStream implements Runnable
|
|||
{
|
||||
synchronized (_inputQ)
|
||||
{
|
||||
long now=System.currentTimeMillis();
|
||||
|
||||
if (_blockingTimeoutAt>=0 && !isAsync())
|
||||
_blockingTimeoutAt=System.currentTimeMillis()+getHttpChannelState().getHttpChannel().getHttpConfiguration().getBlockingTimeout();
|
||||
_blockingTimeoutAt=now+getHttpChannelState().getHttpChannel().getHttpConfiguration().getBlockingTimeout();
|
||||
|
||||
int minRequestDataRate=_channelState.getHttpChannel().getHttpConfiguration().getMinRequestDataRate();
|
||||
if (minRequestDataRate>0)
|
||||
{
|
||||
long period=now-_channelState.getHttpChannel().getRequest().getTimeStamp();
|
||||
if (period>=1000)
|
||||
{
|
||||
long data_rate = _contentArrived / (now-_channelState.getHttpChannel().getRequest().getTimeStamp());
|
||||
if (data_rate<minRequestDataRate)
|
||||
throw new IOException(String.format("Request Data rate %d < %d B/s",data_rate,minRequestDataRate));
|
||||
}
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
Content item = nextContent();
|
||||
|
@ -410,6 +426,7 @@ public class HttpInput extends ServletInputStream implements Runnable
|
|||
boolean woken=false;
|
||||
synchronized (_inputQ)
|
||||
{
|
||||
_contentArrived+=item.remaining();
|
||||
_inputQ.offer(item);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} addContent {}", this, item);
|
||||
|
|
|
@ -546,7 +546,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory
|
|||
};
|
||||
|
||||
// Can we use a memory mapped file?
|
||||
if (_minMemoryMappedContentLength>0 &&
|
||||
if (_minMemoryMappedContentLength>=0 &&
|
||||
resource.length()>_minMemoryMappedContentLength &&
|
||||
resource.length()<Integer.MAX_VALUE &&
|
||||
resource instanceof PathResource)
|
||||
|
|
Loading…
Reference in New Issue