Skip to content

Commit 9406e88

Browse files
Support multiline header fields
1 parent a0fc6a2 commit 9406e88

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

libraries/common/io/requests.effekt

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,28 @@ namespace plain {
391391
case d and d.isAlphanumeric => true
392392
case _ => false
393393
}
394+
def isLWS(c: Char): Bool = c match {
395+
case '\t' => true
396+
case ' ' => true
397+
case _ => false
398+
}
394399

395-
// TODO line continuations
396400
def parseHeaderLine(): (String, String) / { Scan[Char], Exception[WrongFormat] } = {
397401
with returning::expect("HTTP Header line")
398402
val k = collectString { readWhile { c => c.isHTTPTokenChar() } }
399403
readIf(':')
400-
skipWhile { c => c == ' ' || c == '\t' }
401-
val v = collectString { readWhile { c => c != '\r' } }
402-
skipWhile { c => c == ' ' || c == '\t' }
404+
skipWhile { c => c.isLWS }
405+
val v = collectString {
406+
readWhile { c => c != '\r' }
407+
readIf('\r'); readIf('\n')
408+
while(do peek[Char]().isLWS) {
409+
// continuation line
410+
skipWhile { c => c.isLWS }
411+
do emit('\n')
412+
readWhile { c => c != '\r'}
413+
readIf('\r'); readIf('\n')
414+
}
415+
}
403416
(k, v)
404417
}
405418

@@ -431,8 +444,6 @@ namespace plain {
431444
expect("Trailers or end of response"){
432445
while(do peek[Char]() != '\r') {
433446
do emit(parseHeaderLine())
434-
readIf('\r')
435-
readIf('\n')
436447
}
437448
readIf('\r')
438449
readIf('\n')
@@ -459,8 +470,6 @@ namespace plain {
459470
headers = collectList {
460471
while(do peek[Char]() != '\r') {
461472
do emit(parseHeaderLine())
462-
readIf('\r')
463-
readIf('\n')
464473
}
465474
}
466475
readIf('\r')
@@ -680,12 +689,18 @@ namespace example {
680689
crlf()
681690
"content-type: text/plain".each;
682691
crlf()
692+
"x-multiline-test-header: This is the first line".each
693+
crlf()
694+
" and this is the second line".each
695+
crlf()
683696
crlf()
684697
"Hello!".each
685698
}
686699
with def res = plain::parseResponse
687700
println(res.status())
688701
println(res.getHeader("content-type").show{ x => x })
702+
println("X-Multiline-Test-Header:")
703+
println(res.getHeader("x-multiline-test-header").show{ x => x })
689704
with source[Byte]{ res.body() }
690705
with decodeUTF8
691706
with stringBuffer

0 commit comments

Comments
 (0)