Fixes #4764 - HTTP2 Jetty Server does not send back content-length.
Updates after review. Now the Content-Length header is generated by HpackEncoder based on MetaData.contentLength, so that the MetaData.HttpFields are not modified. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
dc89f7f264
commit
2e85b3e169
|
@ -119,6 +119,11 @@ public class MetaData implements Iterable<HttpField>
|
||||||
return _contentLength;
|
return _contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContentLength(long contentLength)
|
||||||
|
{
|
||||||
|
_contentLength = contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an iterator over the HTTP fields
|
* @return an iterator over the HTTP fields
|
||||||
* @see #getFields()
|
* @see #getFields()
|
||||||
|
|
|
@ -217,7 +217,8 @@ public class HpackEncoder
|
||||||
// Remove fields as specified in RFC 7540, 8.1.2.2.
|
// Remove fields as specified in RFC 7540, 8.1.2.2.
|
||||||
if (fields != null)
|
if (fields != null)
|
||||||
{
|
{
|
||||||
// For example: Connection: Close, TE, Upgrade, Custom.
|
// Remove the headers specified in the Connection header,
|
||||||
|
// for example: Connection: Close, TE, Upgrade, Custom.
|
||||||
Set<String> hopHeaders = null;
|
Set<String> hopHeaders = null;
|
||||||
for (String value : fields.getCSV(HttpHeader.CONNECTION, false))
|
for (String value : fields.getCSV(HttpHeader.CONNECTION, false))
|
||||||
{
|
{
|
||||||
|
@ -225,6 +226,8 @@ public class HpackEncoder
|
||||||
hopHeaders = new HashSet<>();
|
hopHeaders = new HashSet<>();
|
||||||
hopHeaders.add(StringUtil.asciiToLowerCase(value));
|
hopHeaders.add(StringUtil.asciiToLowerCase(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean contentLengthEncoded = false;
|
||||||
for (HttpField field : fields)
|
for (HttpField field : fields)
|
||||||
{
|
{
|
||||||
HttpHeader header = field.getHeader();
|
HttpHeader header = field.getHeader();
|
||||||
|
@ -239,8 +242,17 @@ public class HpackEncoder
|
||||||
String name = field.getLowerCaseName();
|
String name = field.getLowerCaseName();
|
||||||
if (hopHeaders != null && hopHeaders.contains(name))
|
if (hopHeaders != null && hopHeaders.contains(name))
|
||||||
continue;
|
continue;
|
||||||
|
if (header == HttpHeader.CONTENT_LENGTH)
|
||||||
|
contentLengthEncoded = true;
|
||||||
encode(buffer, field);
|
encode(buffer, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!contentLengthEncoded)
|
||||||
|
{
|
||||||
|
long contentLength = metadata.getContentLength();
|
||||||
|
if (contentLength >= 0)
|
||||||
|
encode(buffer, new HttpField(HttpHeader.CONTENT_LENGTH, String.valueOf(contentLength)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check size
|
// Check size
|
||||||
|
|
|
@ -22,8 +22,8 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.BadMessageException;
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MetaData;
|
import org.eclipse.jetty.http.MetaData;
|
||||||
|
@ -113,9 +113,17 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
{
|
{
|
||||||
if (lastContent)
|
if (lastContent)
|
||||||
{
|
{
|
||||||
HttpFields responseHeaders = info.getFields();
|
long realContentLength = BufferUtil.length(content);
|
||||||
if (!responseHeaders.contains(HttpHeader.CONTENT_LENGTH))
|
long contentLength = info.getContentLength();
|
||||||
responseHeaders.put(HttpHeader.CONTENT_LENGTH, String.valueOf(BufferUtil.length(content)));
|
if (contentLength < 0)
|
||||||
|
{
|
||||||
|
info.setContentLength(realContentLength);
|
||||||
|
}
|
||||||
|
else if (contentLength != realContentLength)
|
||||||
|
{
|
||||||
|
callback.failed(new BadMessageException(HttpStatus.INTERNAL_SERVER_ERROR_500, String.format("Incorrect Content-Length %d!=%d", contentLength, realContentLength)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasContent)
|
if (hasContent)
|
||||||
|
|
Loading…
Reference in New Issue