@@ -167,6 +167,7 @@ private[engine] final class HttpHeaderParser private (
167
167
private def parseRawHeader (input : ByteString , lineStart : Int , cursor : Int , nodeIx : Int ): Int = {
168
168
val colonIx = input.indexOf(':' , cursor, lineStart + 1 + maxHeaderNameLength)
169
169
if (colonIx == - 1 ) {
170
+ scanIllegalHeaderNameCharacters(input, cursor, lineStart + 1 + maxHeaderNameLength)
170
171
fail(s " HTTP header name exceeds the configured limit of $maxHeaderNameLength characters " ,
171
172
StatusCodes .RequestHeaderFieldsTooLarge )
172
173
} else {
@@ -210,6 +211,32 @@ private[engine] final class HttpHeaderParser private (
210
211
if (start == end) " " else build()
211
212
}
212
213
214
+ // similar to scanAsciiString but only scans for illegal characters and fails or warns if it finds one
215
+ private def scanIllegalHeaderNameCharacters (input : ByteString , start : Int , end : Int ): Unit = {
216
+ @ tailrec def check (ix : Int = start): Unit =
217
+ if (ix == end) {
218
+ ()
219
+ } else {
220
+ val c = input(ix).toChar
221
+ if (tchar(c)) {
222
+ check(ix + 1 )
223
+ } else {
224
+ settings.illegalResponseHeaderNameProcessingMode match {
225
+ case IllegalResponseHeaderNameProcessingMode .Error =>
226
+ fail(s " Illegal character ' ${escape(c)}' in header name " )
227
+ case IllegalResponseHeaderNameProcessingMode .Warn =>
228
+ log.warning(s " Header key contains illegal character ' ${escape(c)}' " )
229
+ check(ix + 1 )
230
+ case IllegalResponseHeaderNameProcessingMode .Ignore =>
231
+ ()
232
+ }
233
+ }
234
+ }
235
+ if (start == end || settings.illegalResponseHeaderNameProcessingMode == IllegalResponseHeaderNameProcessingMode .Ignore )
236
+ ()
237
+ else check()
238
+ }
239
+
213
240
@ tailrec
214
241
private def parseHeaderValue (input : ByteString , valueStart : Int , branch : ValueBranch )(cursor : Int = valueStart,
215
242
nodeIx : Int = branch.branchRootNodeIx): Int = {
0 commit comments