@@ -11,19 +11,89 @@ fn read_body(
1111 body_bytes : BytesView ,
1212) -> HttpBody raise BodyError {
1313 let content_type = req_headers.get("Content -Type ")
14- match content_type {
15- Some ([.. "application/json", ..]) => {
16- let json = @encoding/utf8.decode(body_bytes) catch {
17- _ => raise BodyError ::InvalidJsonCharset
14+ if content_type is Some (content_type) {
15+ let content_type = parse_content_type(content_type)
16+ if content_type is Some (content_type) {
17+ return match content_type {
18+ { subtype: "json", .. } => {
19+ let json = @encoding/utf8.decode(body_bytes) catch {
20+ _ => raise BodyError ::InvalidJsonCharset
21+ }
22+ Json (@json.parse(json) catch { _ => raise BodyError ::InvalidJson })
23+ }
24+ { media_type: "text", .. } =>
25+ Text (
26+ @encoding/utf8.decode(body_bytes) catch {
27+ _ => raise BodyError ::InvalidText
28+ },
29+ )
30+ { subtype: "x-www-form-urlencoded", .. } =>
31+ Form (parse_form_data(body_bytes))
32+ _ => Bytes (body_bytes)
1833 }
19- Json (@json.parse(json) catch { _ => raise BodyError ::InvalidJson })
2034 }
21- Some ([.. "text/plain", ..] | [.. "text/html", ..]) =>
22- Text (
23- @encoding/utf8.decode(body_bytes) catch {
24- _ => raise BodyError ::InvalidText
25- },
26- )
27- _ => Bytes (body_bytes)
2835 }
36+ Bytes (body_bytes)
37+ }
38+
39+ ///|
40+ priv struct ContentType {
41+ media_type : StringView
42+ subtype : StringView
43+ params : Map [StringView , StringView ]
44+ } derive (Show )
45+
46+ ///|
47+ fn parse_content_type(s : String ) -> ContentType? {
48+ let parts = s.split(";").to_array()
49+ if parts.is_empty() {
50+ None
51+ } else {
52+ let main_part_str = parts[0].trim_space()
53+ let media_type_parts = main_part_str.split("/").to_array()
54+ if media_type_parts.length() != 2 {
55+ None
56+ } else {
57+ let media_type = media_type_parts[0].trim_space()
58+ let subtype = media_type_parts[1].trim_space()
59+ let params = {}
60+ for i in 1..<parts.length() {
61+ let param_part = parts[i].trim_space()
62+ let eq_index = param_part.find("=")
63+ try {
64+ match eq_index {
65+ Some (idx) => {
66+ let key = param_part[0:idx].trim_space()
67+ let value = param_part[idx + 1:].trim_space()
68+ params[key] = value
69+ }
70+ None => () // Ignore malformed parameters
71+ }
72+ } catch {
73+ _ => ()
74+ }
75+ }
76+ Some ({ media_type, subtype, params })
77+ }
78+ }
79+ }
80+
81+ ///|
82+ test " parse_content_type " {
83+ inspect(
84+ parse_content_type("application/json; charset=utf-8"),
85+ content=(
86+ #|Some ({media_type: "application", subtype: "json", params: {"charset": "utf-8"}})
87+ ),
88+ )
89+ }
90+
91+ ///|
92+ test " parse_form_data " {
93+ inspect(
94+ parse_form_data(b"name=John +Doe &age=30"),
95+ content=(
96+ #|{"name": "John Doe ", "age": "30"}
97+ ),
98+ )
2999}
0 commit comments