Skip to content

Commit

Permalink
fix #4213: Content-Length when entity is unallowed
Browse files Browse the repository at this point in the history
  • Loading branch information
bursauxa committed Jan 12, 2023
1 parent 84af061 commit ab3bcab
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# IntelliJ
/.idea

# VS Code
**/metals.sbt
**/.bloop
.metals
settings.json

.DS_Store
target

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,21 @@ private[http] class HttpResponseRendererFactory(
r ~~ `Transfer-Encoding` ~~ ChunkedBytes ~~ CrLf
}

def renderContentLengthHeader(contentLength: Long) =
if (status.allowsEntity) r ~~ ContentLengthBytes ~~ contentLength ~~ CrLf else r
def renderContentLengthHeader(contentLength: Long) = {
// evaluate requirements for content-length according to https://httpwg.org/specs/rfc9110.html#field.content-length
// - for HEAD it is technically allowed, but must match the content-length of hypothetical GET request, which is not handled here
// - for 304 (Not Modified) it must similarly match the content-length of hypothetical 200-accepted request, which is not handled here
// - for 1xx (Informational) or 204 (No Content) it is explicitly not allowed
// - for 2xx (Successful) it is explicitly not allowed when the method is CONNECT
val isContentLengthForbidden =
(ctx.requestMethod eq HttpMethods.HEAD) ||
(status eq StatusCodes.NotModified) ||
(100 to 199 contains status.intValue) ||
(status eq StatusCodes.NoContent) ||
((ctx.requestMethod eq HttpMethods.CONNECT) && (200 to 299 contains status.intValue))

if (isContentLengthForbidden) r else r ~~ ContentLengthBytes ~~ contentLength ~~ CrLf
}

def headersAndEntity(entityBytes: => Source[ByteString, Any]): StrictOrStreamed =
if (noEntity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,32 @@ class ResponseRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfter
}
}

"status 304 and a few headers" in new TestSetup() {
"status 204 and a few headers (does not add content-length)" in new TestSetup() {
HttpResponse(204, List(RawHeader("X-Fancy", "of course"), Age(0))) should renderTo {
"""HTTP/1.1 204 No Content
|X-Fancy: of course
|Age: 0
|Server: akka-http/1.0.0
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
|"""
}
}

"status 205 and a few headers (adds content-length)" in new TestSetup() {
HttpResponse(205, List(RawHeader("X-Fancy", "of course"), Age(0))) should renderTo {
"""HTTP/1.1 205 Reset Content
|X-Fancy: of course
|Age: 0
|Server: akka-http/1.0.0
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|Content-Length: 0
|
|"""
}
}

"status 304 and a few headers (does not add content-length)" in new TestSetup() {
HttpResponse(304, List(RawHeader("X-Fancy", "of course"), Age(0))) should renderTo {
"""HTTP/1.1 304 Not Modified
|X-Fancy: of course
Expand All @@ -69,6 +94,7 @@ class ResponseRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfter
|"""
}
}

"a custom status code and no headers" in new TestSetup() {
HttpResponse(ServerOnTheMove) should renderTo {
"""HTTP/1.1 330 Server on the move
Expand Down Expand Up @@ -97,6 +123,18 @@ class ResponseRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfter
override def currentTimeMillis() = initial + extraMillis
}

"no Content-Length on CONNECT method" in new TestSetup() {
ResponseRenderingContext(
requestMethod = HttpMethods.CONNECT,
response = HttpResponse(headers = List(Age(30), Connection("Keep-Alive")))) should renderTo(
"""HTTP/1.1 200 OK
|Age: 30
|Server: akka-http/1.0.0
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
|""")
}

"to a transparent HEAD request (Strict response entity)" in new TestSetup() {
ResponseRenderingContext(
requestMethod = HttpMethods.HEAD,
Expand All @@ -108,7 +146,6 @@ class ResponseRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfter
|Server: akka-http/1.0.0
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|Content-Type: text/plain; charset=UTF-8
|Content-Length: 23
|
|""", close = false)
}
Expand Down

0 comments on commit ab3bcab

Please sign in to comment.