Skip to content

Commit

Permalink
Fix #6562 last written bytebuffer
Browse files Browse the repository at this point in the history
Restored the last flush of an empty buffer as is needed for 0 length empty write.
  • Loading branch information
gregw committed Jul 30, 2021
1 parent 6d2c57c commit 0f6d3e2
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 2 deletions.
Expand Up @@ -863,10 +863,12 @@ public void write(byte[] b, int off, int len) throws IOException
// Blocking write
try
{
boolean complete = false;
// flush any content from the aggregate
if (BufferUtil.hasContent(_aggregate))
{
channelWrite(_aggregate, last && len == 0);
complete = last && len == 0;
channelWrite(_aggregate, complete);

// should we fill aggregate again from the buffer?
if (len > 0 && !last && len <= _commitSize && len <= maximizeAggregateSpace())
Expand Down Expand Up @@ -896,6 +898,10 @@ public void write(byte[] b, int off, int len) throws IOException
}
channelWrite(view, last);
}
else if (last && !complete)
{
channelWrite(BufferUtil.EMPTY_BUFFER, true);
}

onWriteComplete(last, null);
}
Expand Down Expand Up @@ -963,12 +969,18 @@ public void write(ByteBuffer buffer) throws IOException
{
// Blocking write
// flush any content from the aggregate
boolean complete = false;
if (BufferUtil.hasContent(_aggregate))
channelWrite(_aggregate, last && len == 0);
{
complete = last && len == 0;
channelWrite(_aggregate, complete);
}

// write any remaining content in the buffer directly
if (len > 0)
channelWrite(buffer, last);
else if (last && !complete)
channelWrite(BufferUtil.EMPTY_BUFFER, true);

onWriteComplete(last, null);
}
Expand Down
Expand Up @@ -28,6 +28,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
Expand Down Expand Up @@ -763,6 +764,102 @@ public void setNext(Interceptor interceptor)
assertThat(response, containsString("400\tTHIS IS A BIGGER FILE"));
}

@Test
public void testEmptyArray() throws Exception
{
AtomicBoolean committed = new AtomicBoolean();
AbstractHandler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
response.getOutputStream().write(new byte[0]);
committed.set(response.isCommitted());
}
};

_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(committed.get(), is(false));
}

@Test
public void testEmptyArrayKnown() throws Exception
{
AtomicBoolean committed = new AtomicBoolean();
AbstractHandler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
response.setContentLength(0);
response.getOutputStream().write(new byte[0]);
committed.set(response.isCommitted());
}
};

_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("Content-Length: 0"));
assertThat(committed.get(), is(true));
}

@Test
public void testEmptyBuffer() throws Exception
{
AtomicBoolean committed = new AtomicBoolean();
AbstractHandler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
((HttpOutput)response.getOutputStream()).write(ByteBuffer.wrap(new byte[0]));
committed.set(response.isCommitted());
}
};

_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(committed.get(), is(false));
}

@Test
public void testEmptyBufferKnown() throws Exception
{
AtomicBoolean committed = new AtomicBoolean();
AbstractHandler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(200);
response.setContentLength(0);
((HttpOutput)response.getOutputStream()).write(ByteBuffer.wrap(new byte[0]));
committed.set(response.isCommitted());
}
};

_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("Content-Length: 0"));
assertThat(committed.get(), is(true));
}

@Test
public void testAggregation() throws Exception
{
Expand Down

0 comments on commit 0f6d3e2

Please sign in to comment.