-
Notifications
You must be signed in to change notification settings - Fork 48
avoid ByteString when parsing HTTP/2 headers #800
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,6 @@ import pekko.http.scaladsl.model._ | |
import pekko.http.scaladsl.model.headers.`Tls-Session-Info` | ||
import pekko.http.scaladsl.settings.ServerSettings | ||
import pekko.stream.Attributes | ||
import pekko.util.ByteString | ||
import pekko.util.OptionVal | ||
|
||
import scala.annotation.tailrec | ||
|
@@ -191,13 +190,21 @@ private[http2] object RequestParsing { | |
} | ||
|
||
private[http2] def parseHeaderPair(httpHeaderParser: HttpHeaderParser, name: String, value: String): HttpHeader = { | ||
// FIXME: later modify by adding HttpHeaderParser.parseHttp2Header that would use (name, value) pair directly | ||
// or use a separate, simpler, parser for Http2 | ||
// The odd-looking 'x' below is a by-product of how current parser and HTTP/1.1 work. | ||
// Without '\r\n\x' (x being any additional byte) parsing will fail. See HttpHeaderParserSpec for examples. | ||
val concHeaderLine = name + ": " + value + "\r\nx" | ||
httpHeaderParser.parseHeaderLine(ByteString(concHeaderLine))() | ||
httpHeaderParser.resultHeader | ||
import HttpHeader.ParsingResult | ||
if (name.startsWith(":")) { | ||
// HttpHeader.parse used in `else` block does not support pseudo-headers (that have ':' prefix in header name) | ||
// The odd-looking 'x' below is a by-product of how current parser and HTTP/1.1 work. | ||
// Without '\r\n\x' (x being any additional byte) parsing will fail. See HttpHeaderParserSpec for examples. | ||
val concHeaderLine = s"$name: $value\r\nx" | ||
httpHeaderParser.parseHeaderLine(pekko.util.ByteString(concHeaderLine))() | ||
httpHeaderParser.resultHeader | ||
} else { | ||
HttpHeader.parse(name, value, httpHeaderParser.settings) match { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general that's really cleaner. I don't expect a performance hit, there's a bit of a difference of how the parsers are looked up between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @jrudolph. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's annoying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But wait, does it even parse it into anything useful? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll debug it later. There is an existing test that relies on the header parser not failing. Whether it needs the parser to actually process the pseudo header at all is something that I haven't yet tested. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's a typo in the test? Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pekko-grpc also doesn't use the colon form so maybe it's just a typo and we could just fix the test. |
||
case ParsingResult.Ok(header, errors) if errors.isEmpty => header | ||
case ParsingResult.Ok(_, errors) => throw ParsingException(errors.head) | ||
case ParsingResult.Error(info) => throw ParsingException(info) | ||
} | ||
} | ||
} | ||
|
||
private[http2] def checkRequiredPseudoHeader(name: String, value: AnyRef): Unit = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just a look ahead char is better