AtlatestRepositorysigil-http
sigil-http / tree / testtest-multipart-bytes.sgl
1
(import (sigil io)2
(sigil test)3
(sigil http request))5
(define (wrap bytes ending)6
(bytevector-append (string->utf8 "--boundary\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\né雪\r\n--boundary\r\nContent-Disposition: form-data; name=\"logo\"; filename=\"test.png\"\r\nContent-Type: image/png\r\n\r\n") bytes (string->utf8 ending)))7
(define binary (make-bytevector 256))8
(let loop ((i 0))9
(when (< i 256)10
(bytevector-u8-set! binary i i)11
(loop (+ i 1))))12
(test-group "byte multipart"13
(test "UTF-8 fields decode independently of arbitrary file bytes"14
(let* ((parts (parse-multipart-form-data-bytes (wrap binary "\r\n--boundary--\r\n") "boundary"))15
(file (dict-ref (cdr (assoc 'logo parts)) content:)))16
(assert-equal (cdr (assoc 'title parts)) "é雪")17
(assert-equal (bytevector-length file) 256)18
(let loop ((i 0))19
(when (< i 256)20
(assert-equal (bytevector-u8-ref file i) i)21
(loop (+ i 1))))))22
(test "file trailing CRLF and boundary lookalikes are retained"23
(let* ((payload "x\r\n--boundaryX\r\n ")24
(parts (parse-multipart-form-data-bytes (wrap (string->utf8 payload) "\r\n--boundary--") "boundary")))25
(assert-equal (utf8->string (dict-ref (cdr (assoc 'logo parts)) content:)) payload)))26
(test "empty file stays a zero-length bytevector"27
(let ((parts (parse-multipart-form-data-bytes (wrap (make-bytevector 0) "\r\n--boundary--\r\n") "boundary")))28
(assert-equal (bytevector-length (dict-ref (cdr (assoc 'logo parts)) content:)) 0)))29
(test "truncated and malformed boundaries fail"30
(assert-error (parse-multipart-form-data-bytes (wrap binary "") "boundary"))31
(assert-error (parse-multipart-form-data-bytes (wrap binary "\r\n--boundary--oops") "boundary"))32
(assert-error (parse-multipart-form-data-bytes binary "")))33
(test "auto parser uses raw bytes even if body text was decoded"34
(let* ((raw (wrap binary "\r\n--boundary--\r\n"))35
(req (http-request method: 'POST path: "/" query: #f version: "HTTP/1.1"36
headers: #{ content-type: "multipart/form-data; boundary=boundary" }37
body: "damaged text" raw-body: raw))38
(parts (parse-form-data req)))39
(assert-equal (bytevector-length (dict-ref (cdr (assoc 'logo parts)) content:)) 256))))