diff --git a/src/Tiny_httpd_util.ml b/src/Tiny_httpd_util.ml index f2b769e2..370384f6 100644 --- a/src/Tiny_httpd_util.ml +++ b/src/Tiny_httpd_util.ml @@ -1,7 +1,7 @@ (* test utils *) (*$inject - let pp_res f = function Ok x -> f x | Error e -> Printexc.to_string e + let pp_res f = function Ok x -> f x | Error e -> e let pp_res_query = (Q.Print.(pp_res (list (pair string string)))) let err_map f = function Ok x-> Ok (f x) | Error e -> Error e let sort_l l = List.sort compare l @@ -17,7 +17,7 @@ let percent_encode ?(skip=fun _->false) s = | (' ' | '!' | '"' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' | '*' | '+' | ',' | '/' | ':' | ';' | '=' | '?' | '@' | '[' | ']' | '~') as c -> - Printf.bprintf buf "%%%x" (Char.code c) + Printf.bprintf buf "%%%X" (Char.code c) | c -> Buffer.add_char buf c) s; Buffer.contents buf @@ -25,7 +25,11 @@ let percent_encode ?(skip=fun _->false) s = (*$= & ~printer:(fun s->s) "hello%20world" (percent_encode "hello world") "%23%25^%24%40^%40" (percent_encode "#%^$@^@") - "a%20ohm%2b5235%25%26%40%23%20---%20_" (percent_encode "a ohm+5235%&@# --- _") + "a%20ohm%2B5235%25%26%40%23%20---%20_" (percent_encode "a ohm+5235%&@# --- _") +*) + +(*$= & ~printer:Q.(Print.(option string)) + (Some "?") (percent_decode @@ percent_encode "?") *) let hex_int (s:string) : int = Scanf.sscanf s "%x" (fun x->x) @@ -60,16 +64,21 @@ let percent_decode (s:string) : _ option = | None -> Q.Test.fail_report "invalid percent encoding") *) -let parse_query s : (_ list, _) result= +exception Invalid_query + +let parse_query s : (_ list, string) result= let pairs = ref [] in let is_sep_ = function '&' | ';' -> true | _ -> false in + let i = ref 0 in + let j = ref 0 in try - let i = ref 0 in - let j = ref 0 in + let percent_decode s = + match percent_decode s with Some x -> x | None -> raise Invalid_query + in let parse_pair () = let eq = String.index_from s !i '=' in - let k = String.sub s !i (eq- !i) in - let v = String.sub s (eq+1) (!j-eq-1) in + let k = percent_decode @@ String.sub s !i (eq- !i) in + let v = percent_decode @@ String.sub s (eq+1) (!j-eq-1) in pairs := (k,v) :: !pairs; in while !i < String.length s do @@ -85,7 +94,10 @@ let parse_query s : (_ list, _) result= ) done; Ok !pairs - with e -> Error e + with + | Invalid_argument _ | Not_found | Failure _ -> + Error (Printf.sprintf "error in parse_query for %S: i=%d,j=%d" s !i !j) + | Invalid_query -> Error ("invalid query string: " ^ s) (*$= & ~printer:pp_res_query ~cmp:eq_sorted (Ok ["a", "b"; "c", "d"]) (parse_query "a=b&c=d") diff --git a/src/Tiny_httpd_util.mli b/src/Tiny_httpd_util.mli index dada640b..32de8908 100644 --- a/src/Tiny_httpd_util.mli +++ b/src/Tiny_httpd_util.mli @@ -13,7 +13,7 @@ val percent_decode : string -> string option (** Inverse operation of {!percent_encode}. Can fail since some strings are not valid percent encodings. *) -val parse_query : string -> ((string*string) list, exn) result +val parse_query : string -> ((string*string) list, string) result (** Parse a query as a list of ['&'] or [';'] separated [key=value] pairs. The order might not be preserved. @since 0.3