in finagle-netty4-http/src/main/scala/com/twitter/finagle/netty4/http/Bijections.scala [162:239]
def chunkedResponseToNetty(r: Response): NettyHttp.HttpResponse =
new NettyHttp.DefaultHttpResponse(
versionToNetty(r.version),
statusToNetty(r.status),
headersToNetty(r.headerMap)
)
def fullResponseToNetty(r: Response): NettyHttp.FullHttpResponse =
new NettyHttp.DefaultFullHttpResponse(
versionToNetty(r.version),
statusToNetty(r.status),
ByteBufConversion.bufAsByteBuf(r.content),
headersToNetty(r.headerMap),
NettyHttp.EmptyHttpHeaders.INSTANCE // trailers are only propagated from chunked messages
)
def methodToNetty(m: Method): NettyHttp.HttpMethod =
NettyHttp.HttpMethod.valueOf(m.toString)
def requestToNetty(r: Request, contentLengthHeader: Option[Long]): NettyHttp.HttpRequest = {
if (r.isChunked) {
val result = new NettyHttp.DefaultHttpRequest(
versionToNetty(r.version),
methodToNetty(r.method),
r.uri,
headersToNetty(r.headerMap)
)
// We only set the Transfer-Encoding to "chunked" if the request does not have
// Content-Length set. This mimics Netty 3 behavior, wherein a request can be "chunked"
// and not have a "Transfer-Encoding: chunked" header (instead, it has a Content-Length).
if (!r.headerMap.contains(Fields.ContentLength)) {
result.headers
.add(NettyHttp.HttpHeaderNames.TRANSFER_ENCODING, NettyHttp.HttpHeaderValues.CHUNKED)
} else {
// Make sure we don't have a `Transfer-Encoding: chunked` header and `Content-Length` headers
result.headers.remove(NettyHttp.HttpHeaderNames.TRANSFER_ENCODING)
}
result
} else {
val result = new NettyHttp.DefaultFullHttpRequest(
versionToNetty(r.version),
methodToNetty(r.method),
r.uri,
ByteBufConversion.bufAsByteBuf(r.content),
headersToNetty(r.headerMap),
NettyHttp.EmptyHttpHeaders.INSTANCE // trailers are only propagated from chunked messages
)
if (contentLengthHeader.isDefined) {
result.headers.remove(NettyHttp.HttpHeaderNames.TRANSFER_ENCODING)
}
val realLength = r.content.length
// see https://tools.ietf.org/html/rfc7230#section-3.3.2
contentLengthHeader match {
case Some(l) if realLength != l =>
// need to clean up the content length header
result.headers.set(NettyHttp.HttpHeaderNames.CONTENT_LENGTH, realLength.toString)
case None if realLength > 0 =>
// Set the content length if we are sure there is content.
result.headers.set(NettyHttp.HttpHeaderNames.CONTENT_LENGTH, realLength.toString)
case None if shouldHaveLengthHeader(r.method) =>
// RFC 7230: "A user agent SHOULD send a Content-Length in a request message
// when no Transfer-Encoding is sent and the request method defines a meaning
// for an enclosed payload body."
result.headers.set(NettyHttp.HttpHeaderNames.CONTENT_LENGTH, realLength.toString)
case _ =>
// NOP. Either the content length header already matches or
// it doesn't exist for messages that should not have 0 value (see allowEmpty),
// so there is nothing to do.
}
result
}
}