Merge branch 'jetty-9.2.x' into feature/gziphandler-config

This commit is contained in:
Joakim Erdfelt 2015-12-08 14:56:26 -07:00
commit 7cdc58e6b9
6 changed files with 96 additions and 40 deletions

View File

@ -323,27 +323,34 @@ public abstract class HttpReceiver
}
else
{
List<ByteBuffer> decodeds = new ArrayList<>(2);
while (buffer.hasRemaining())
try
{
ByteBuffer decoded = decoder.decode(buffer);
if (!decoded.hasRemaining())
continue;
decodeds.add(decoded);
if (LOG.isDebugEnabled())
LOG.debug("Response content decoded ({}) {}{}{}", decoder, response, System.lineSeparator(), BufferUtil.toDetailString(decoded));
}
List<ByteBuffer> decodeds = new ArrayList<>(2);
while (buffer.hasRemaining())
{
ByteBuffer decoded = decoder.decode(buffer);
if (!decoded.hasRemaining())
continue;
decodeds.add(decoded);
if (LOG.isDebugEnabled())
LOG.debug("Response content decoded ({}) {}{}{}", decoder, response, System.lineSeparator(), BufferUtil.toDetailString(decoded));
}
if (decodeds.isEmpty())
{
callback.succeeded();
if (decodeds.isEmpty())
{
callback.succeeded();
}
else
{
int size = decodeds.size();
CountingCallback counter = new CountingCallback(callback, size);
for (int i = 0; i < size; ++i)
notifier.notifyContent(listeners, response, decodeds.get(i), counter);
}
}
else
catch (Throwable x)
{
int size = decodeds.size();
CountingCallback counter = new CountingCallback(callback, size);
for (int i = 0; i < size; ++i)
notifier.notifyContent(listeners, response, decodeds.get(i), counter);
callback.failed(x);
}
}

View File

@ -205,8 +205,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
parser.setHeadResponse(HttpMethod.HEAD.is(method) || HttpMethod.CONNECT.is(method));
exchange.getResponse().version(version).status(status).reason(reason);
responseBegin(exchange);
return false;
return !responseBegin(exchange);
}
@Override
@ -216,8 +215,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
if (exchange == null)
return false;
responseHeader(exchange, field);
return false;
return !responseHeader(exchange, field);
}
@Override
@ -227,8 +225,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
if (exchange == null)
return false;
responseHeaders(exchange);
return false;
return !responseHeaders(exchange);
}
@Override
@ -253,17 +250,20 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
failAndClose(x);
}
};
responseContent(exchange, buffer, callback);
return callback.tryComplete();
// Do not short circuit these calls.
boolean proceed = responseContent(exchange, buffer, callback);
boolean async = callback.tryComplete();
return !proceed || async;
}
@Override
public boolean messageComplete()
{
HttpExchange exchange = getHttpExchange();
if (exchange != null)
responseSuccess(exchange);
return false;
if (exchange == null)
return false;
return !responseSuccess(exchange);
}
@Override

View File

@ -22,14 +22,18 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -195,6 +199,37 @@ public class HttpClientGZIPTest extends AbstractHttpClientServerTest
Assert.assertArrayEquals(data, response.getContent());
}
@Test
public void testGZIPContentCorrupted() throws Exception
{
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setHeader("Content-Encoding", "gzip");
// Not gzipped, will cause the client to blow up.
response.getOutputStream().print("0123456789");
}
});
final CountDownLatch latch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
if (result.isFailed())
latch.countDown();
}
});
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
private static void sleep(long ms) throws IOException
{
try

View File

@ -377,9 +377,10 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
close(x);
}
};
if (!channel.content(buffer, callback))
return true;
return callback.tryComplete();
// Do not short circuit these calls.
boolean proceed = channel.content(buffer, callback);
boolean async = callback.tryComplete();
return !proceed || async;
}
else
{

View File

@ -24,6 +24,7 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.DispatcherType;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
@ -42,6 +43,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{
private final String _encoding;
protected final String _vary;
private final HttpServletRequest _request;
protected final CompressedResponseWrapper _wrapper;
protected final HttpServletResponse _response;
protected OutputStream _out;
@ -58,10 +60,11 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
throws IOException
{
_encoding=encoding;
_request = request;
_wrapper = wrapper;
_response = (HttpServletResponse)wrapper.getResponse();
_vary=vary;
if (_wrapper.getMinCompressSize()==0)
doCompress();
}
@ -90,7 +93,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
_bOut=b;
}
}
/* ------------------------------------------------------------ */
public void setContentLength()
{
@ -241,9 +244,11 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_encoding!=null)
{
String prefix=Response.getResponse(_response).isIncluding()?Response.SET_INCLUDE_HEADER_PREFIX:"";
String prefix = "";
if (_request.getDispatcherType() == DispatcherType.INCLUDE)
prefix = Response.SET_INCLUDE_HEADER_PREFIX;
setHeader(prefix+"Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding"))
{
addHeader(prefix+"Vary",_vary);
@ -269,7 +274,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
}
}
}
doNotCompress(true); // Send vary as it could have been compressed if encoding was present
}
}
@ -290,7 +295,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
addHeader("Vary",_vary);
if (_wrapper.getETag()!=null)
setHeader("ETag",_wrapper.getETag());
_doNotCompress = true;
_out = _response.getOutputStream();
@ -316,7 +321,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
throw new IOException("CLOSED");
if (_out == null)
{
{
// If this first write is larger than buffer size, then we are committing now
if (lengthToWrite>_wrapper.getBufferSize())
{
@ -336,7 +341,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
// else are we aggregating writes?
else if (_bOut !=null)
{
// We are aggregating into the buffered output stream.
// We are aggregating into the buffered output stream.
// If this write fills the buffer, then we are committing
if (lengthToWrite>=(_bOut.getBuf().length - _bOut.getCount()))
@ -384,7 +389,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{
throw new UnsupportedOperationException("Use AsyncGzipFilter");
}
@Override
public boolean isReady()

View File

@ -82,6 +82,10 @@ public abstract class CompletableCallback implements Callback
}
break;
}
case FAILED:
{
return;
}
default:
{
throw new IllegalStateException(current.toString());
@ -108,6 +112,10 @@ public abstract class CompletableCallback implements Callback
}
break;
}
case FAILED:
{
return;
}
default:
{
throw new IllegalStateException(current.toString());