dream: multipart/form-data parsing + 9 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 14:47:10 +00:00
parent 9a67ced748
commit fbc0c03f3a
3 changed files with 199 additions and 6 deletions

View File

@@ -1,4 +1,4 @@
;; lib/dream/tests/form.sx — urlencoded parsing, Ok/Err, CSRF accept/reject.
;; lib/dream/tests/form.sx — urlencoded parsing, Ok/Err, CSRF accept/reject, multipart.
(define dream-fo-pass 0)
(define dream-fo-fail 0)
@@ -100,14 +100,12 @@
(define dream-fo-backend (dream-memory-sessions))
(define dream-fo-sid (dream-fo-backend {:op "session/create"})) ;; s1
;; build a request already carrying the session cookie + csrf middleware applied
(define
dream-fo-stack
(fn
(handler)
((dream-sessions dream-fo-backend) ((dream-csrf "topsecret") handler))))
;; a handler that emits its csrf tag
(define
dream-fo-tag-out
(dream-resp-body
@@ -122,7 +120,6 @@
(contains? dream-fo-tag-out "name=\"dream.csrf\"")
true)
;; valid token (signed for s1) -> dream-form Ok
(define
dream-fo-good-token
(dr/csrf-make-token dream-csrf-sign-default "topsecret" "s1"))
@@ -178,4 +175,52 @@
(str "dream.csrf=" dream-fo-good-token))))
"reached")
;; ── multipart/form-data ────────────────────────────────────────────
(define
dream-fo-mp-body
(str
"--B1\r\n"
"Content-Disposition: form-data; name=\"title\"\r\n\r\n"
"Hello\r\n"
"--B1\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\nContent-Type: text/plain\r\n\r\n"
"line1\r\nline2\r\n"
"--B1--\r\n"))
(define
dream-fo-mp-req
(dream-request "POST" "/upload" {:Content-Type "multipart/form-data; boundary=B1"} dream-fo-mp-body))
(define dream-fo-mp (dream-multipart dream-fo-mp-req))
(dream-fo-test "multipart is Ok" (dream-ok? dream-fo-mp) true)
(define dream-fo-parts (dream-ok-value dream-fo-mp))
(dream-fo-test "two parts" (len dream-fo-parts) 2)
(dream-fo-test
"field value"
(dream-multipart-field dream-fo-parts "title")
"Hello")
(dream-fo-test
"file part filename"
(get (dream-multipart-file dream-fo-parts "file") :filename)
"a.txt")
(dream-fo-test
"file content-type"
(get (dream-multipart-file dream-fo-parts "file") :content-type)
"text/plain")
(dream-fo-test
"file content keeps inner CRLF"
(get (dream-multipart-file dream-fo-parts "file") :content)
"line1\r\nline2")
(dream-fo-test
"field is not a file"
(get (dream-multipart-file dream-fo-parts "title") :filename)
nil)
(dream-fo-test
"non-multipart is Err"
(dream-err? (dream-multipart (dream-request "POST" "/x" {:Content-Type "text/plain"} "hi")))
true)
(dream-fo-test
"quoted boundary parsed"
(dream-ok?
(dream-multipart (dream-request "POST" "/u" {:Content-Type "multipart/form-data; boundary=\"B1\""} dream-fo-mp-body)))
true)
(define dream-fo-tests-run! (fn () {:total (+ dream-fo-pass dream-fo-fail) :passed dream-fo-pass :failed dream-fo-fail :fails dream-fo-fails}))