Skip to content

Commit

Permalink
Merge pull request #1345 from rmartinc/UNDERTOW-2116-22x
Browse files Browse the repository at this point in the history
[UNDERTOW-2116] ServletOutputStreamImpl incorrectly sets Content-Length to 0
  • Loading branch information
fl4via committed Jul 19, 2022
2 parents 4b520b1 + 84a3a9e commit f7589af
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public void doErrorDispatch(int sc, String error) throws IOException {
writer = null;
responseState = ResponseState.NONE;
resetBuffer();
exchange.getResponseHeaders().remove(Headers.CONTENT_LENGTH);
treatAsCommitted = false;
final String location = servletContext.getDeployment().getErrorPages().getErrorLocation(sc);
if (location != null) {
Expand Down Expand Up @@ -190,6 +191,7 @@ public void sendRedirect(final String location) throws IOException {
throw UndertowServletMessages.MESSAGES.responseAlreadyCommited();
}
resetBuffer();
exchange.getResponseHeaders().remove(Headers.CONTENT_LENGTH);
setStatus(StatusCodes.FOUND);
String realPath;
if (isAbsoluteUrl(location)) {//absolute url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import io.undertow.servlet.UndertowServletMessages;
import io.undertow.servlet.handlers.ServletRequestContext;
import io.undertow.util.Headers;
import io.undertow.util.Methods;

/**
* This stream essentially has two modes. When it is being used in standard blocking mode then
Expand Down Expand Up @@ -607,9 +608,10 @@ public void close() throws IOException {
if (servletRequestContext.getOriginalResponse().getHeader(Headers.TRANSFER_ENCODING_STRING) == null
&& servletRequestContext.getExchange().getAttachment(HttpAttachments.RESPONSE_TRAILER_SUPPLIER) == null
&& servletRequestContext.getExchange().getAttachment(HttpAttachments.RESPONSE_TRAILERS) == null) {
if (buffer == null) {
final String contentLength = servletRequestContext.getOriginalResponse().getHeader(Headers.CONTENT_LENGTH_STRING);
if (buffer == null && (contentLength == null || !Methods.HEAD_STRING.equals(servletRequestContext.getOriginalRequest().getMethod()))) {
servletRequestContext.getExchange().getResponseHeaders().put(Headers.CONTENT_LENGTH, "0");
} else if (servletRequestContext.getOriginalResponse().getHeader(Headers.CONTENT_LENGTH_STRING) == null) {
} else if (buffer != null && contentLength == null) {
servletRequestContext.getExchange().getResponseHeaders().put(Headers.CONTENT_LENGTH, Integer.toString(buffer.position()));
}
}
Expand Down Expand Up @@ -675,11 +677,14 @@ public void run() {
clearFlags(FLAG_READY);
if (allAreClear(state, FLAG_WRITE_STARTED) && channel == null) {

if (servletRequestContext.getOriginalResponse().getHeader(Headers.TRANSFER_ENCODING_STRING) == null) {
if (buffer == null) {
servletRequestContext.getOriginalResponse().setHeader(Headers.CONTENT_LENGTH, "0");
} else {
servletRequestContext.getOriginalResponse().setHeader(Headers.CONTENT_LENGTH, Integer.toString(buffer.position()));
if (servletRequestContext.getOriginalResponse().getHeader(Headers.TRANSFER_ENCODING_STRING) == null
&& servletRequestContext.getExchange().getAttachment(HttpAttachments.RESPONSE_TRAILER_SUPPLIER) == null
&& servletRequestContext.getExchange().getAttachment(HttpAttachments.RESPONSE_TRAILERS) == null) {
final String contentLength = servletRequestContext.getOriginalResponse().getHeader(Headers.CONTENT_LENGTH_STRING);
if (buffer == null && (contentLength == null || !Methods.HEAD_STRING.equals(servletRequestContext.getOriginalRequest().getMethod()))) {
servletRequestContext.getExchange().getResponseHeaders().put(Headers.CONTENT_LENGTH, "0");
} else if (buffer != null && contentLength == null) {
servletRequestContext.getExchange().getResponseHeaders().put(Headers.CONTENT_LENGTH, Integer.toString(buffer.position()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@
import io.undertow.servlet.test.util.TestClassIntrospector;
import io.undertow.testutils.DefaultServer;
import io.undertow.testutils.HttpClientUtils;
import io.undertow.testutils.TestHttpClient;
import io.undertow.util.Headers;
import io.undertow.util.StatusCodes;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import io.undertow.testutils.TestHttpClient;
import org.apache.http.client.methods.HttpHead;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
Expand Down Expand Up @@ -87,4 +91,19 @@ public void testSimpleHttpServlet() throws IOException {
}
}

@Test
public void testSimpleHttpServletHead() throws IOException {
TestHttpClient client = new TestHttpClient();
try {
HttpHead head = new HttpHead(DefaultServer.getDefaultServerURL() + "/servletContext/aa");
HttpResponse result = client.execute(head);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
Assert.assertEquals("", HttpClientUtils.readResponse(result));
Assert.assertNotNull(result.getHeaders(Headers.CONTENT_LENGTH_STRING));
Assert.assertEquals(1, result.getHeaders(Headers.CONTENT_LENGTH_STRING).length);
Assert.assertEquals(HELLO_WORLD.length(), Integer.parseInt(result.getFirstHeader(Headers.CONTENT_LENGTH_STRING).getValue()));
} finally {
client.getConnectionManager().shutdown();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -78,4 +81,58 @@ public void testServletRedirect() throws Exception {
client.getConnectionManager().shutdown();
}
}
}

@Test
public void testServletRedirectNoFollow() throws Exception {
final String requestURL = DefaultServer.getDefaultServerURL() + "/servletContext/redirect/";
final String expectedRedirect = DefaultServer.getDefaultServerURL() + "/servletContext/redirect/subpath";
try (CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build()) {
HttpGet get = new HttpGet(requestURL);
HttpResponse result = client.execute(get);
assertEquals(StatusCodes.FOUND, result.getStatusLine().getStatusCode());
assertEquals("", HttpClientUtils.readResponse(result));
Header[] header = result.getHeaders(Headers.CONTENT_LENGTH_STRING);
assertEquals(1, header.length);
assertEquals(0, Integer.parseInt(header[0].getValue()));
header = result.getHeaders(Headers.LOCATION_STRING);
assertEquals(1, header.length);
assertEquals(expectedRedirect, header[0].getValue());
}
}

@Test
public void testServletRedirectHead() throws Exception {
final String requestURL = DefaultServer.getDefaultServerURL() + "/servletContext/redirect/";
final String expectedBody = "/servletContext/redirect/subpath";
TestHttpClient client = new TestHttpClient();
try {
HttpHead head = new HttpHead(requestURL);
HttpResponse result = client.execute(head);
assertEquals("", HttpClientUtils.readResponse(result));
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
Header[] header = result.getHeaders(Headers.CONTENT_LENGTH_STRING);
assertEquals(1, header.length);
assertEquals(expectedBody.length(), Integer.parseInt(header[0].getValue()));
} finally {
client.getConnectionManager().shutdown();
}
}

@Test
public void testServletRedirectHeadNoFollow() throws Exception {
final String requestURL = DefaultServer.getDefaultServerURL() + "/servletContext/redirect/";
final String expectedRedirect = DefaultServer.getDefaultServerURL() + "/servletContext/redirect/subpath";
try (CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build()) {
HttpHead head = new HttpHead(requestURL);
HttpResponse result = client.execute(head);
assertEquals(StatusCodes.FOUND, result.getStatusLine().getStatusCode());
assertEquals("", HttpClientUtils.readResponse(result));
Header[] header = result.getHeaders(Headers.CONTENT_LENGTH_STRING);
assertEquals(1, header.length);
assertEquals(0, Integer.parseInt(header[0].getValue()));
header = result.getHeaders(Headers.LOCATION_STRING);
assertEquals(1, header.length);
assertEquals(expectedRedirect, header[0].getValue());
}
}
}

0 comments on commit f7589af

Please sign in to comment.