Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-3578-epl2
This commit is contained in:
commit
f4fc78ac66
|
@ -25,11 +25,6 @@
|
|||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-servlet-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
|
@ -40,14 +35,6 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-modules jetty.servlet.api
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
|
|
|
@ -26,9 +26,6 @@ module org.eclipse.jetty.http
|
|||
|
||||
requires transitive org.eclipse.jetty.io;
|
||||
|
||||
// Only required if using the MultiPart classes.
|
||||
requires static jetty.servlet.api;
|
||||
|
||||
uses HttpFieldPreEncoder;
|
||||
|
||||
provides HttpFieldPreEncoder with Http1FieldPreEncoder;
|
||||
|
|
|
@ -276,7 +276,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
|
|||
public static final String DEFAULT_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZ";
|
||||
|
||||
public static final String NCSA_FORMAT = "%{client}a - %u %t \"%r\" %s %O";
|
||||
public static final String EXTENDED_NCSA_FORMAT = "%{client}a - %u %t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"";
|
||||
public static final String EXTENDED_NCSA_FORMAT = NCSA_FORMAT + " \"%{Referer}i\" \"%{User-Agent}i\"";
|
||||
|
||||
private static ThreadLocal<StringBuilder> _buffers = ThreadLocal.withInitial(() -> new StringBuilder(256));
|
||||
|
||||
|
@ -287,6 +287,21 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
|
|||
private final MethodHandle _logHandle;
|
||||
private final String _formatString;
|
||||
|
||||
public CustomRequestLog()
|
||||
{
|
||||
this(new Slf4jRequestLogWriter(), EXTENDED_NCSA_FORMAT);
|
||||
}
|
||||
|
||||
public CustomRequestLog(String file)
|
||||
{
|
||||
this(file, EXTENDED_NCSA_FORMAT);
|
||||
}
|
||||
|
||||
public CustomRequestLog(String file, String format)
|
||||
{
|
||||
this(new RequestLogWriter(file), format);
|
||||
}
|
||||
|
||||
public CustomRequestLog(RequestLog.Writer writer, String formatString)
|
||||
{
|
||||
_formatString = formatString;
|
||||
|
@ -303,16 +318,6 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
|
|||
}
|
||||
}
|
||||
|
||||
public CustomRequestLog(String file)
|
||||
{
|
||||
this(file, EXTENDED_NCSA_FORMAT);
|
||||
}
|
||||
|
||||
public CustomRequestLog(String file, String format)
|
||||
{
|
||||
this(new RequestLogWriter(file), format);
|
||||
}
|
||||
|
||||
@ManagedAttribute("The RequestLogWriter")
|
||||
public RequestLog.Writer getWriter()
|
||||
{
|
||||
|
|
|
@ -366,6 +366,18 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
return wake;
|
||||
}
|
||||
|
||||
private int maximizeAggregateSpace()
|
||||
{
|
||||
// If no aggregate, we can allocate one of bufferSize
|
||||
if (_aggregate == null)
|
||||
return getBufferSize();
|
||||
|
||||
// compact to maximize space
|
||||
BufferUtil.compact(_aggregate);
|
||||
|
||||
return BufferUtil.space(_aggregate);
|
||||
}
|
||||
|
||||
public void softClose()
|
||||
{
|
||||
synchronized (_channelState)
|
||||
|
@ -711,6 +723,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("write(array {})", BufferUtil.toDetailString(ByteBuffer.wrap(b, off, len)));
|
||||
|
||||
boolean last;
|
||||
boolean aggregate;
|
||||
boolean flush;
|
||||
|
@ -721,7 +736,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
checkWritable();
|
||||
long written = _written + len;
|
||||
int space = _aggregate == null ? getBufferSize() : BufferUtil.space(_aggregate);
|
||||
int space = maximizeAggregateSpace();
|
||||
last = _channel.getResponse().isAllContentWritten(written);
|
||||
// Write will be aggregated if:
|
||||
// + it is smaller than the commitSize
|
||||
|
@ -765,7 +780,12 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
// return if we are not complete, not full and filled all the content
|
||||
if (!flush)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("write(array) {} aggregated !flush {}",
|
||||
stateString(), BufferUtil.toDetailString(_aggregate));
|
||||
return;
|
||||
}
|
||||
|
||||
// adjust offset/length
|
||||
off += filled;
|
||||
|
@ -773,6 +793,10 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("write(array) {} last={} agg={} flush=true async={}, len={} {}",
|
||||
stateString(), last, aggregate, async, len, BufferUtil.toDetailString(_aggregate));
|
||||
|
||||
if (async)
|
||||
{
|
||||
// Do the asynchronous writing from the callback
|
||||
|
@ -789,9 +813,10 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
channelWrite(_aggregate, last && len == 0);
|
||||
|
||||
// should we fill aggregate again from the buffer?
|
||||
if (len > 0 && !last && len <= _commitSize && len <= BufferUtil.space(_aggregate))
|
||||
if (len > 0 && !last && len <= _commitSize && len <= maximizeAggregateSpace())
|
||||
{
|
||||
BufferUtil.append(_aggregate, b, off, len);
|
||||
onWriteComplete(false, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -917,7 +942,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
checkWritable();
|
||||
long written = _written + 1;
|
||||
int space = _aggregate == null ? getBufferSize() : BufferUtil.space(_aggregate);
|
||||
int space = maximizeAggregateSpace();
|
||||
last = _channel.getResponse().isAllContentWritten(written);
|
||||
flush = last || space == 1;
|
||||
|
||||
|
@ -1554,7 +1579,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
private final ByteBuffer _buffer;
|
||||
private final ByteBuffer _slice;
|
||||
private final int _len;
|
||||
volatile boolean _completed;
|
||||
private boolean _completed;
|
||||
|
||||
AsyncWrite(byte[] b, int off, int len, boolean last)
|
||||
{
|
||||
|
@ -1591,7 +1616,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
|
||||
// Can we just aggregate the remainder?
|
||||
if (!_last && _len < BufferUtil.space(_aggregate) && _len < _commitSize)
|
||||
if (!_last && _aggregate != null && _len < maximizeAggregateSpace() && _len < _commitSize)
|
||||
{
|
||||
int position = BufferUtil.flipToFill(_aggregate);
|
||||
BufferUtil.put(_buffer, _aggregate);
|
||||
|
@ -1790,32 +1815,16 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
private class WriteCompleteCB implements Callback
|
||||
{
|
||||
final Callback _callback;
|
||||
|
||||
WriteCompleteCB()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
WriteCompleteCB(Callback callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
onWriteComplete(true, null);
|
||||
if (_callback != null)
|
||||
_callback.succeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
onWriteComplete(true, x);
|
||||
if (_callback != null)
|
||||
_callback.succeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
|
@ -16,13 +16,15 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpParser.RequestHandler;
|
||||
import org.eclipse.jetty.http.HttpTokens;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.SearchPattern;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
|
@ -81,7 +81,6 @@ import org.eclipse.jetty.http.HttpURI;
|
|||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.MultiPartFormInputStream;
|
||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
|
|
|
@ -375,7 +375,7 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
|
|||
int len = slice.remaining();
|
||||
_crc.update(array, off, len);
|
||||
_deflater.setInput(array, off, len); // TODO use ByteBuffer API in Jetty-10
|
||||
BufferUtil.clear(slice);
|
||||
slice.position(slice.position() + len);
|
||||
if (_last && BufferUtil.isEmpty(_content))
|
||||
_deflater.finish();
|
||||
}
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.servlet.AsyncContext;
|
||||
|
@ -31,6 +34,7 @@ import javax.servlet.WriteListener;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.server.HttpOutput.Interceptor;
|
||||
import org.eclipse.jetty.server.LocalConnector.LocalEndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
|
@ -54,6 +58,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
*/
|
||||
public class HttpOutputTest
|
||||
{
|
||||
public static final int OUTPUT_AGGREGATION_SIZE = 1024;
|
||||
public static final int OUTPUT_BUFFER_SIZE = 4096;
|
||||
private Server _server;
|
||||
private LocalConnector _connector;
|
||||
private ContentHandler _handler;
|
||||
|
@ -64,10 +70,25 @@ public class HttpOutputTest
|
|||
{
|
||||
_server = new Server();
|
||||
|
||||
_server.addBean(new ByteBufferPool()
|
||||
{
|
||||
@Override
|
||||
public ByteBuffer acquire(int size, boolean direct)
|
||||
{
|
||||
return direct ? BufferUtil.allocateDirect(size) : BufferUtil.allocate(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
http.getHttpConfiguration().setRequestHeaderSize(1024);
|
||||
http.getHttpConfiguration().setResponseHeaderSize(1024);
|
||||
http.getHttpConfiguration().setOutputBufferSize(4096);
|
||||
http.getHttpConfiguration().setOutputBufferSize(OUTPUT_BUFFER_SIZE);
|
||||
http.getHttpConfiguration().setOutputAggregationSize(OUTPUT_AGGREGATION_SIZE);
|
||||
|
||||
_connector = new LocalConnector(_server, http, null);
|
||||
_server.addConnector(_connector);
|
||||
|
@ -670,6 +691,318 @@ public class HttpOutputTest
|
|||
assertThat(response, containsString("400\tTHIS IS A BIGGER FILE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregation() throws Exception
|
||||
{
|
||||
AggregateHandler handler = new AggregateHandler();
|
||||
_swap.setHandler(handler);
|
||||
handler.start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString(handler.expected.toString()));
|
||||
}
|
||||
|
||||
static class AggregateHandler extends AbstractHandler
|
||||
{
|
||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
HttpOutput out = (HttpOutput)response.getOutputStream();
|
||||
|
||||
// Add interceptor to check aggregation is done
|
||||
HttpOutput.Interceptor interceptor = out.getInterceptor();
|
||||
out.setInterceptor(new AggregationChecker(interceptor));
|
||||
|
||||
int bufferSize = baseRequest.getHttpChannel().getHttpConfiguration().getOutputBufferSize();
|
||||
int len = bufferSize * 3 / 2;
|
||||
|
||||
byte[] data = new byte[AggregationChecker.MAX_SIZE];
|
||||
int fill = 0;
|
||||
while (expected.size() < len)
|
||||
{
|
||||
Arrays.fill(data, (byte)('A' + (fill++ % 26)));
|
||||
expected.write(data);
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncAggregation() throws Exception
|
||||
{
|
||||
AsyncAggregateHandler handler = new AsyncAggregateHandler();
|
||||
_swap.setHandler(handler);
|
||||
handler.start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString(handler.expected.toString()));
|
||||
}
|
||||
|
||||
static class AsyncAggregateHandler extends AbstractHandler
|
||||
{
|
||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
HttpOutput out = (HttpOutput)response.getOutputStream();
|
||||
|
||||
// Add interceptor to check aggregation is done
|
||||
HttpOutput.Interceptor interceptor = out.getInterceptor();
|
||||
out.setInterceptor(new AggregationChecker(interceptor));
|
||||
|
||||
int bufferSize = baseRequest.getHttpChannel().getHttpConfiguration().getOutputBufferSize();
|
||||
int len = bufferSize * 3 / 2;
|
||||
|
||||
AsyncContext async = request.startAsync();
|
||||
out.setWriteListener(new WriteListener()
|
||||
{
|
||||
int fill = 0;
|
||||
|
||||
@Override
|
||||
public void onWritePossible() throws IOException
|
||||
{
|
||||
byte[] data = new byte[AggregationChecker.MAX_SIZE];
|
||||
while (out.isReady())
|
||||
{
|
||||
if (expected.size() >= len)
|
||||
{
|
||||
async.complete();
|
||||
return;
|
||||
}
|
||||
|
||||
Arrays.fill(data, (byte)('A' + (fill++ % 26)));
|
||||
expected.write(data);
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t)
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class AggregationChecker implements Interceptor
|
||||
{
|
||||
static final int MAX_SIZE = OUTPUT_AGGREGATION_SIZE / 2 - 1;
|
||||
private final Interceptor interceptor;
|
||||
|
||||
public AggregationChecker(Interceptor interceptor)
|
||||
{
|
||||
this.interceptor = interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuffer content, boolean last, Callback callback)
|
||||
{
|
||||
if (content.remaining() <= MAX_SIZE)
|
||||
throw new IllegalStateException("Not Aggregated!");
|
||||
interceptor.write(content, last, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interceptor getNextInterceptor()
|
||||
{
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregateResidue() throws Exception
|
||||
{
|
||||
AggregateResidueHandler handler = new AggregateResidueHandler();
|
||||
_swap.setHandler(handler);
|
||||
handler.start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString(handler.expected.toString()));
|
||||
}
|
||||
|
||||
static class AggregateResidueHandler extends AbstractHandler
|
||||
{
|
||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
HttpOutput out = (HttpOutput)response.getOutputStream();
|
||||
|
||||
int bufferSize = baseRequest.getHttpChannel().getHttpConfiguration().getOutputBufferSize();
|
||||
int commitSize = baseRequest.getHttpChannel().getHttpConfiguration().getOutputAggregationSize();
|
||||
char fill = 'A';
|
||||
|
||||
// write data that will be aggregated
|
||||
byte[] data = new byte[commitSize - 1];
|
||||
Arrays.fill(data, (byte)(fill++));
|
||||
expected.write(data);
|
||||
out.write(data);
|
||||
int aggregated = data.length;
|
||||
|
||||
// write data that will almost fill the aggregate buffer
|
||||
while (aggregated < (bufferSize - 1))
|
||||
{
|
||||
data = new byte[Math.min(commitSize - 1, bufferSize - aggregated - 1)];
|
||||
Arrays.fill(data, (byte)(fill++));
|
||||
expected.write(data);
|
||||
out.write(data);
|
||||
aggregated += data.length;
|
||||
}
|
||||
|
||||
// write data that will not be aggregated
|
||||
data = new byte[bufferSize + 1];
|
||||
Arrays.fill(data, (byte)(fill++));
|
||||
expected.write(data);
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrint() throws Exception
|
||||
{
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
PrintWriter exp = new PrintWriter(bout);
|
||||
_swap.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setCharacterEncoding("UTF8");
|
||||
HttpOutput out = (HttpOutput)response.getOutputStream();
|
||||
|
||||
exp.print("\u20AC\u0939\uD55C");
|
||||
out.print("\u20AC\u0939\uD55C");
|
||||
exp.print("zero");
|
||||
out.print("zero");
|
||||
exp.print(1);
|
||||
out.print(1);
|
||||
exp.print(2L);
|
||||
out.print(2L);
|
||||
exp.print(3.0F);
|
||||
out.print(3.0F);
|
||||
exp.print('4');
|
||||
out.print('4');
|
||||
exp.print(5.0D);
|
||||
out.print(5.0D);
|
||||
exp.print(true);
|
||||
out.print(true);
|
||||
exp.println("zero");
|
||||
out.println("zero");
|
||||
exp.println(-1);
|
||||
out.println(-1);
|
||||
exp.println(-2L);
|
||||
out.println(-2L);
|
||||
exp.println(-3.0F);
|
||||
out.println(-3.0F);
|
||||
exp.println('4');
|
||||
out.println('4');
|
||||
exp.println(-5.0D);
|
||||
out.println(-5.0D);
|
||||
exp.println(false);
|
||||
out.println(false);
|
||||
}
|
||||
});
|
||||
_swap.getHandler().start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString(bout.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReset() throws Exception
|
||||
{
|
||||
ByteArrayOutputStream exp = new ByteArrayOutputStream();
|
||||
_swap.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
HttpOutput out = (HttpOutput)response.getOutputStream();
|
||||
Interceptor interceptor = out.getInterceptor();
|
||||
out.setInterceptor(new Interceptor()
|
||||
{
|
||||
@Override
|
||||
public void write(ByteBuffer content, boolean last, Callback callback)
|
||||
{
|
||||
interceptor.write(content, last, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interceptor getNextInterceptor()
|
||||
{
|
||||
return interceptor;
|
||||
}
|
||||
});
|
||||
|
||||
out.setBufferSize(128);
|
||||
out.println("NOT TO BE SEEN!");
|
||||
out.resetBuffer();
|
||||
|
||||
byte[] data = "TO BE SEEN\n".getBytes(StandardCharsets.ISO_8859_1);
|
||||
exp.write(data);
|
||||
out.write(data);
|
||||
|
||||
out.flush();
|
||||
|
||||
data = "Not reset after flush\n".getBytes(StandardCharsets.ISO_8859_1);
|
||||
exp.write(data);
|
||||
try
|
||||
{
|
||||
out.resetBuffer();
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
_swap.getHandler().start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString(exp.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroLengthWrite() throws Exception
|
||||
{
|
||||
_swap.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setContentLength(0);
|
||||
AsyncContext async = request.startAsync();
|
||||
response.getOutputStream().setWriteListener(new WriteListener()
|
||||
{
|
||||
@Override
|
||||
public void onWritePossible() throws IOException
|
||||
{
|
||||
response.getOutputStream().write(new byte[0]);
|
||||
async.complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t)
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
_swap.getHandler().start();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
}
|
||||
|
||||
private static String toUTF8String(Resource resource)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -682,8 +1015,6 @@ public class HttpOutputTest
|
|||
{
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
void setNext(Interceptor interceptor);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -31,7 +31,7 @@ import javax.servlet.ReadListener;
|
|||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.eclipse.jetty.http.MultiPartFormInputStream.MultiPart;
|
||||
import org.eclipse.jetty.server.MultiPartFormInputStream.MultiPart;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -16,14 +16,15 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import org.eclipse.jetty.http.MultiPartParser.State;
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.server.MultiPartParser.State;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Test;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue