;; lib/dream/tests/static.sx — content types, etags, 304, ranges, traversal. (define dream-st-pass 0) (define dream-st-fail 0) (define dream-st-fails (list)) (define dream-st-test (fn (name actual expected) (if (= actual expected) (set! dream-st-pass (+ dream-st-pass 1)) (begin (set! dream-st-fail (+ dream-st-fail 1)) (append! dream-st-fails {:name name :actual actual :expected expected}))))) ;; ── content type + ext ───────────────────────────────────────────── (dream-st-test "ext css" (dr/ext-of "a/b/style.css") "css") (dream-st-test "ext multi-dot" (dr/ext-of "a.min.js") "js") (dream-st-test "ext none" (dr/ext-of "README") "") (dream-st-test "ctype css" (dream-content-type-for "x.css") "text/css; charset=utf-8") (dream-st-test "ctype html" (dream-content-type-for "x.html") "text/html; charset=utf-8") (dream-st-test "ctype png" (dream-content-type-for "x.png") "image/png") (dream-st-test "ctype unknown" (dream-content-type-for "x.bin") "application/octet-stream") ;; ── etag ─────────────────────────────────────────────────────────── (dream-st-test "etag deterministic" (= (dr/etag-of "abc") (dr/etag-of "abc")) true) (dream-st-test "etag content-sensitive" (= (dr/etag-of "abc") (dr/etag-of "abd")) false) (dream-st-test "etag length-sensitive" (= (dr/etag-of "ab") (dr/etag-of "abc")) false) ;; ── serving via router mount ─────────────────────────────────────── (define dream-st-files {:/srv/app.css "body{color:red}" :/srv/index.html "

Hi

"}) (define dream-st-fs (dream-memory-fs dream-st-files)) (define dream-st-app (dream-router (list (dream-get "/static/**" (dream-static-with "/srv" dream-st-fs))))) (define dream-st-get (fn (target headers) (dream-st-app (dream-request "GET" target headers "")))) (define dream-st-css (dream-st-get "/static/app.css" {})) (dream-st-test "serve status 200" (dream-status dream-st-css) 200) (dream-st-test "serve body" (dream-resp-body dream-st-css) "body{color:red}") (dream-st-test "serve content-type" (dream-resp-header dream-st-css "content-type") "text/css; charset=utf-8") (dream-st-test "serve accept-ranges" (dream-resp-header dream-st-css "accept-ranges") "bytes") (dream-st-test "serve has etag" (not (nil? (dream-resp-header dream-st-css "etag"))) true) (dream-st-test "missing file 404" (dream-status (dream-st-get "/static/nope.txt" {})) 404) (dream-st-test "traversal blocked 403" (dream-status (dream-st-get "/static/../secret" {})) 403) ;; ── conditional: If-None-Match -> 304 ────────────────────────────── (define dream-st-etag (dream-resp-header dream-st-css "etag")) (define dream-st-304 (dream-st-get "/static/app.css" {:If-None-Match dream-st-etag})) (dream-st-test "matching etag 304" (dream-status dream-st-304) 304) (dream-st-test "304 empty body" (dream-resp-body dream-st-304) "") (dream-st-test "stale etag 200" (dream-status (dream-st-get "/static/app.css" {:If-None-Match "\"stale\""})) 200) (dream-st-test "star etag 304" (dream-status (dream-st-get "/static/app.css" {:If-None-Match "*"})) 304) ;; ── range requests ───────────────────────────────────────────────── (define dream-st-range (dream-st-get "/static/app.css" {:Range "bytes=0-3"})) (dream-st-test "range status 206" (dream-status dream-st-range) 206) (dream-st-test "range body slice" (dream-resp-body dream-st-range) "body") (dream-st-test "range content-range" (dream-resp-header dream-st-range "content-range") "bytes 0-3/15") (define dream-st-open (dream-st-get "/static/app.css" {:Range "bytes=5-"})) (dream-st-test "open range body" (dream-resp-body dream-st-open) "color:red}") (dream-st-test "open range header" (dream-resp-header dream-st-open "content-range") "bytes 5-14/15") (define dream-st-bad (dream-st-get "/static/app.css" {:Range "bytes=20-30"})) (dream-st-test "unsatisfiable range 416" (dream-status dream-st-bad) 416) (dream-st-test "416 content-range" (dream-resp-header dream-st-bad "content-range") "bytes */15") (define dream-st-tests-run! (fn () {:total (+ dream-st-pass dream-st-fail) :passed dream-st-pass :failed dream-st-fail :fails dream-st-fails}))