@@ -318,8 +318,8 @@ namespace jsWeb {
318
318
namespace plain {
319
319
def constructRequest{ body: => Unit / RequestBuilder }: Unit / emit[Byte] = {
320
320
def crlf() = {
321
- do emit('\n'.toInt.toByte)
322
321
do emit('\r'.toInt.toByte)
322
+ do emit('\n'.toInt.toByte)
323
323
}
324
324
325
325
with encodeUTF8
@@ -397,11 +397,49 @@ namespace plain {
397
397
val k = collectString { readWhile { c => c.isHTTPTokenChar() } }
398
398
readIf(':')
399
399
skipWhile { c => c == ' ' || c == '\t' }
400
- val v = collectString { readWhile { c => c != '\n ' } }
400
+ val v = collectString { readWhile { c => c != '\r ' } }
401
401
skipWhile { c => c == ' ' || c == '\t' }
402
402
(k, v)
403
403
}
404
404
405
+ /// Decode a chunked transfer coding as per RFC 2616.
406
+ /// Emits the contents as bytes, and headers from the trailer.
407
+ def unchunk(): Int / { emit[Byte], emit[(String, String)], read[Byte], Exception[WrongFormat] } = {
408
+ with decodeUTF8
409
+ with returning::scanner[Char, Int]
410
+ var length = 0
411
+ loop { {l} =>
412
+ // chunk header
413
+ val size = returning::expect("chunk header"){
414
+ val size = collectString{ readWhile{ c => c.isHexDigit } }.toInt(16)
415
+ val extensions = collectString{ readWhile{ c => c != '\r' } } // ignored
416
+ if(size == 0){ l.break() }
417
+ readIf('\r')
418
+ readIf('\n')
419
+ size
420
+ }
421
+ // chunk body
422
+ length = length + size
423
+ repeat(size){
424
+ try {
425
+ do emit(do read[Byte]())
426
+ } with stop { () => do raise(WrongFormat(), "Premature end of chunk in chunked encoding") }
427
+ }
428
+ }
429
+ // trailer headers
430
+ expect("Trailers or end of response"){
431
+ while(do peek[Char]() != '\r') {
432
+ do emit(parseHeaderLine())
433
+ readIf('\r')
434
+ readIf('\n')
435
+ }
436
+ readIf('\r')
437
+ readIf('\n')
438
+ }
439
+ // return total length
440
+ length
441
+ }
442
+
405
443
def parseResponse[R]{ body: {ResponseReader} => R }: R / { read[Byte], Exception[WrongFormat] } = {
406
444
with decodeUTF8
407
445
with returning::scanner[Char, R]
@@ -414,18 +452,18 @@ namespace plain {
414
452
statusCode = readInteger()
415
453
if (statusCode > 599 || statusCode < 100) { do raise(WrongFormat(), "Invalid status code") }
416
454
readIf(' ')
417
- val reason = collectString{ readWhile{ c => c != '\n' } }
418
- readIf('\n')
455
+ val reason = collectString{ readWhile{ c => c != '\r' } }
419
456
readIf('\r')
457
+ readIf('\n')
420
458
headers = collectList {
421
- while(do peek[Char]() != '\n ') {
459
+ while(do peek[Char]() != '\r ') {
422
460
do emit(parseHeaderLine())
423
- readIf('\n')
424
461
readIf('\r')
462
+ readIf('\n')
425
463
}
426
464
}
427
- readIf('\n')
428
465
readIf('\r')
466
+ readIf('\n')
429
467
}
430
468
431
469
try body{res} with res: ResponseReader {
@@ -633,8 +671,8 @@ namespace example {
633
671
})
634
672
with source[Byte]{
635
673
def crlf() = {
636
- do emit('\n'.toInt.toByte)
637
674
do emit('\r'.toInt.toByte)
675
+ do emit('\n'.toInt.toByte)
638
676
}
639
677
with encodeUTF8;
640
678
"HTTP/1.1 200 OK".each;
0 commit comments