Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@

package org.apache.pekko.http.impl.engine

import java.lang.{ StringBuilder => JStringBuilder }
import org.apache.pekko
import pekko.http.scaladsl.settings.ParserSettings

import scala.annotation.tailrec
import pekko.event.LoggingAdapter
import pekko.util.ByteString
import pekko.http.scaladsl.model.{ ErrorInfo, StatusCode, StatusCodes }
import pekko.http.impl.util.ISO88591
import pekko.http.impl.util.SingletonException

/**
Expand All @@ -41,11 +40,13 @@ package object parsing {
private[http] def byteAt(input: ByteString, ix: Int): Byte =
if (ix < input.length) input(ix) else throw NotEnoughDataException

private[http] def asciiString(input: ByteString, start: Int, end: Int): String = {
@tailrec def build(ix: Int = start, sb: JStringBuilder = new JStringBuilder(end - start)): String =
if (ix == end) sb.toString else build(ix + 1, sb.append(input(ix).toChar))
if (start == end) "" else build()
}
/**
* Decodes the given range as a String, one character per byte. Bytes above 0x7F are decoded as
* ISO-8859-1, as [[pekko.http.impl.util.ByteStringParserInput.sliceString]] already does; most
* callers have validated the range as 7-bit ASCII, for which the two agree.
*/
private[http] def asciiString(input: ByteString, start: Int, end: Int): String =
if (start == end) "" else input.slice(start, end).decodeString(ISO88591)

private[http] def logParsingError(info: ErrorInfo, log: LoggingAdapter,
settings: ParserSettings.ErrorLoggingVerbosity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ abstract class ResponseParserSpec(mode: String, newLine: String) extends PekkoSp
closeAfterResponseCompletion shouldEqual Seq(false)
}

"a response with a non-ASCII header name, when illegal header names are ignored" in new Test {
override def parserSettings: ParserSettings =
super.parserSettings.withIllegalResponseHeaderNameProcessingMode(
ParserSettings.IllegalResponseHeaderNameProcessingMode.Ignore)

// a header name that is not 7-bit ASCII is an opaque byte range, decoded one character per
// byte (ISO-8859-1) rather than sign extended into \uFFxx characters
val name = new String("f\u00f6o".getBytes(java.nio.charset.StandardCharsets.UTF_8),
java.nio.charset.StandardCharsets.ISO_8859_1)
s"HTTP/1.1 200 OK${newLine}föo: bar${newLine}Content-Length: 0${newLine}${newLine}" should parseTo(
HttpResponse(headers = List(RawHeader(name, "bar"))))
closeAfterResponseCompletion shouldEqual Seq(false)
}

"a response with a missing reason phrase" in new Test {
s"HTTP/1.1 404 ${newLine}Content-Length: 0${newLine}${newLine}" should parseTo(HttpResponse(NotFound))
closeAfterResponseCompletion shouldEqual Seq(false)
Expand Down