Skip to content

Commit

Permalink
Make Response parser more relaxed on reason message akka#981
Browse files Browse the repository at this point in the history
Proposal for issue akka#981 that will allow to parse a non-standard
Http Response which does not contain a status message.

Example: 'HTTP/1.1 400' instead of 'HTTP/1.1 400 Bad Request'
  • Loading branch information
athieriot committed Mar 27, 2017
1 parent 0106fc9 commit 918a210
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,31 @@ private[http] class HttpResponseParser(protected val settings: ParserSettings, p
}
}
}

def isLF(idx: Int) = byteChar(input, idx) == '\n'
def isCRLF(idx: Int) = byteChar(input, idx) == '\r' && isLF(idx + 1)
def isNewLine(idx: Int) = isLF(idx) || isCRLF(idx)

def skipNewLine(idx: Int) = {
if (isCRLF(idx)) idx + 2
else if (isLF(idx)) idx + 1
else idx
}

if (byteChar(input, cursor + 3) == ' ') {
parseStatusCode()
val startIdx = cursor + 4
@tailrec def skipReason(idx: Int): Int =
if (idx - startIdx <= maxResponseReasonLength)
if (byteChar(input, idx) == '\r' && byteChar(input, idx + 1) == '\n') idx + 2
else if (byteChar(input, idx) == '\n') idx + 1
if (isNewLine(idx)) skipNewLine(idx)
else skipReason(idx + 1)
else throw new ParsingException("Response reason phrase exceeds the configured limit of " +
maxResponseReasonLength + " characters")
skipReason(startIdx)
} else if (byteChar(input, cursor + 3) == '\n' || byteChar(input, cursor + 3) == '\r' && byteChar(input, cursor + 4) == '\n') {
throw new ParsingException("Status code misses trailing space")
} else if (isNewLine(cursor + 3)) {
// Status format with no reason phrase and no trailing space accepted, diverging from the spec
// See https://github.com/akka/akka-http/pull/989
skipNewLine(cursor + 3)
} else badStatusCode
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ abstract class ResponseParserSpec(mode: String, newLine: String) extends FreeSpe
closeAfterResponseCompletion shouldEqual Seq(false)
}

"a response with no reason phrase and no trailing space" in new Test {
s"""HTTP/1.1 200${newLine}Content-Length: 0${newLine}${newLine}""".stripMargin should parseTo(HEAD, HttpResponse())
closeAfterResponseCompletion shouldEqual Seq(false)
}

"a response funky `Transfer-Encoding` header" in new Test {
override def parserSettings: ParserSettings =
super.parserSettings.withCustomStatusCodes(ServerOnTheMove)
Expand Down Expand Up @@ -242,11 +247,6 @@ abstract class ResponseParserSpec(mode: String, newLine: String) extends FreeSpe
Seq("HTTP/1.1 204 12345678", s"90123456789012${newLine}") should generalMultiParseTo(Left(
MessageStartError(400: StatusCode, ErrorInfo("Response reason phrase exceeds the configured limit of 21 characters"))))
}

"with a missing reason phrase and no trailing space" in new Test {
Seq(s"HTTP/1.1 200${newLine}Content-Length: 0${newLine}${newLine}") should generalMultiParseTo(Left(MessageStartError(
400: StatusCode, ErrorInfo("Status code misses trailing space"))))
}
}
}

Expand Down

0 comments on commit 918a210

Please sign in to comment.