diff --git a/src/Tiny_httpd.ml b/src/Tiny_httpd.ml index 7d62eb1e..72e0f528 100644 --- a/src/Tiny_httpd.ml +++ b/src/Tiny_httpd.ml @@ -351,6 +351,11 @@ module Request = struct let path self = self.path let body self = self.body + let query self = + match Tiny_httpd_util.(parse_query @@ get_query self.path) with + | Ok l -> l + | Error e -> bad_reqf 400 "invalid query: %s" e + let get_header ?f self h = Headers.get ?f h self.headers let get_header_int self h = match get_header self h with | Some x -> (try Some (int_of_string x) with _ -> None) diff --git a/src/Tiny_httpd.mli b/src/Tiny_httpd.mli index d5b4824d..8ec54bdc 100644 --- a/src/Tiny_httpd.mli +++ b/src/Tiny_httpd.mli @@ -233,6 +233,10 @@ module Request : sig val path : _ t -> string (** Request path. *) + val query : _ t -> (string*string) list + (** Decode the query part of the {!path} field + @since NEXT_RELEASE *) + val body : 'b t -> 'b (** Request body, possibly empty. *) diff --git a/src/Tiny_httpd_util.ml b/src/Tiny_httpd_util.ml index 370384f6..1822386d 100644 --- a/src/Tiny_httpd_util.ml +++ b/src/Tiny_httpd_util.ml @@ -66,6 +66,11 @@ let percent_decode (s:string) : _ option = exception Invalid_query +let get_query s : string = + match String.index s '?' with + | i -> String.sub s (i+1) (String.length s-i-1) + | exception Not_found -> "" + let parse_query s : (_ list, string) result= let pairs = ref [] in let is_sep_ = function '&' | ';' -> true | _ -> false in diff --git a/src/Tiny_httpd_util.mli b/src/Tiny_httpd_util.mli index 32de8908..681900c6 100644 --- a/src/Tiny_httpd_util.mli +++ b/src/Tiny_httpd_util.mli @@ -13,6 +13,10 @@ val percent_decode : string -> string option (** Inverse operation of {!percent_encode}. Can fail since some strings are not valid percent encodings. *) +val get_query : string -> string +(** Obtain the query part of a path + @since NEXT_RELEASE *) + 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. diff --git a/src/examples/echo.ml b/src/examples/echo.ml index a9365b92..9d1025c1 100644 --- a/src/examples/echo.ml +++ b/src/examples/echo.ml @@ -16,7 +16,13 @@ let () = "/hello/%s@/" (fun name _req -> S.Response.make_string (Ok ("hello " ^name ^"!\n"))); (* echo request *) S.add_path_handler server - "/echo" (fun req -> S.Response.make_string (Ok (Format.asprintf "echo:@ %a@." S.Request.pp req))); + "/echo" (fun req -> + let q = + S.Request.query req |> List.map (fun (k,v) -> Printf.sprintf "%S = %S" k v) + |> String.concat ";" + in + S.Response.make_string + (Ok (Format.asprintf "echo:@ %a@ (query: %s)@." S.Request.pp req q))); S.add_path_handler ~meth:`PUT server "/upload/%s" (fun path req -> S._debug (fun k->k "start upload %S\n%!" path);