Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions http.carp
Original file line number Diff line number Diff line change
Expand Up @@ -567,18 +567,24 @@ Returns `(Maybe String)`.")
(Result.Error e) (IO.errorln &e))
```")
(defmodule Form
(private form-unescape)
(hidden form-unescape)
(defn form-unescape [s]
(URI.unescape &(String.join " " &(String.split-by s &[\+]))))

(doc parse "parses a URL-encoded form body into a `(Map String String)`.
Keys and values are percent-decoded.")
Keys and values are percent-decoded. The `+` character is decoded as space
per the `application/x-www-form-urlencoded` specification.")
(defn parse [s]
(let-do [m (the (Map String String) {})
pairs &(String.split-by s &[\&])]
(for [i 0 (Array.length pairs)]
(let [pair (Array.unsafe-nth pairs i)
eq (String.index-of pair \=)]
(if (= eq -1)
(let [k (URI.unescape pair)] (Map.put! &m &k ""))
(let [k (URI.unescape &(String.byte-slice pair 0 eq))
v (URI.unescape
(let [k (form-unescape pair)] (Map.put! &m &k ""))
(let [k (form-unescape &(String.byte-slice pair 0 eq))
v (form-unescape
&(String.byte-slice pair (Int.inc eq) (String.length pair)))]
(Map.put! &m &k &v)))))
(Result.Success m))))
Expand Down
29 changes: 29 additions & 0 deletions test/http.carp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,35 @@
_ @"FAIL")
"Form.parse handles key without value")

(assert-equal test
"hello world"
&(match (the (Result (Map String String) String)
(Form.parse "msg=hello+world"))
(Result.Success m) (Map.get &m "msg")
_ @"")
"Form.parse decodes + as space")

(assert-equal test
"a b c"
&(match (the (Result (Map String String) String) (Form.parse "x=a+b+c"))
(Result.Success m) (Map.get &m "x")
_ @"")
"Form.parse decodes multiple + as spaces")

(assert-equal test
"+"
&(match (the (Result (Map String String) String) (Form.parse "x=%2B"))
(Result.Success m) (Map.get &m "x")
_ @"")
"Form.parse decodes %2B as literal +")

(assert-equal test
"a b"
&(match (the (Result (Map String String) String) (Form.parse "key+name=a+b"))
(Result.Success m) (Map.get &m "key name")
_ @"")
"Form.parse decodes + in keys too")

; ---------------------------------------------------------------------------
; Request.ignore-body?
; ---------------------------------------------------------------------------
Expand Down
Loading