Skip to content

Commit 2a955bc

Browse files
committed
feat: add rest_of_path_urlencoded and rename rest to rest_of_path
1 parent 9dd94b0 commit 2a955bc

File tree

3 files changed

+28
-12
lines changed

3 files changed

+28
-12
lines changed

src/Tiny_httpd.ml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -688,11 +688,14 @@ module Route = struct
688688

689689
type (_, _) t =
690690
| Fire : ('b, 'b) t
691-
| Rest : (string -> 'b, 'b) t
691+
| Rest : {
692+
url_encoded: bool;
693+
} -> (string -> 'b, 'b) t
692694
| Compose: ('a, 'b) comp * ('b, 'c) t -> ('a, 'c) t
693695

694696
let return = Fire
695-
let rest = Rest
697+
let rest_of_path = Rest {url_encoded=false}
698+
let rest_of_path_urlencoded = Rest {url_encoded=true}
696699
let (@/) a b = Compose (a,b)
697700
let string = String
698701
let string_urlencoded = String_urlencoded
@@ -705,9 +708,19 @@ module Route = struct
705708
begin match path, route with
706709
| [], Fire -> Some f
707710
| _, Fire -> None
708-
| _, Rest ->
711+
| _, Rest {url_encoded} ->
709712
let whole_path = String.concat "/" path in
710-
Some (f whole_path)
713+
begin match
714+
if url_encoded
715+
then match Tiny_httpd_util.percent_decode whole_path with
716+
| Some s -> s
717+
| None -> raise_notrace Exit
718+
else whole_path
719+
with
720+
| whole_path ->
721+
Some (f whole_path)
722+
| exception Exit -> None
723+
end
711724
| (c1 :: path'), Compose (comp, route') ->
712725
begin match comp with
713726
| Int ->
@@ -735,7 +748,8 @@ module Route = struct
735748
: type a b. Buffer.t -> (a,b) t -> unit
736749
= fun out -> function
737750
| Fire -> bpf out "/"
738-
| Rest -> bpf out "<rest>"
751+
| Rest {url_encoded} ->
752+
bpf out "<rest_of_url%s>" (if url_encoded then "_urlencoded" else "")
739753
| Compose (Exact s, tl) -> bpf out "%s/%a" s pp_ tl
740754
| Compose (Int, tl) -> bpf out "<int>/%a" pp_ tl
741755
| Compose (String, tl) -> bpf out "<str>/%a" pp_ tl

src/Tiny_httpd.mli

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,11 +397,16 @@ module Route : sig
397397
val return : ('a, 'a) t
398398
(** Matches the empty path. *)
399399

400-
val rest : (string -> 'a, 'a) t
400+
val rest_of_path : (string -> 'a, 'a) t
401401
(** Matches a string, even containing ['/']. This will match
402402
the entirety of the remaining route.
403403
@since NEXT_RELEASE *)
404404

405+
val rest_of_path_urlencoded : (string -> 'a, 'a) t
406+
(** Matches a string, even containing ['/'], an URL-decode it.
407+
This will match the entirety of the remaining route.
408+
@since NEXT_RELEASE *)
409+
405410
val (@/) : ('a, 'b) comp -> ('b, 'c) t -> ('a, 'c) t
406411
(** [comp / route] matches ["foo/bar/…"] iff [comp] matches ["foo"],
407412
and [route] matches ["bar/…"]. *)

src/bin/http_of_dir.ml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,8 @@ let serve ~config (dir:string) : _ result =
116116
dir (if S.is_ipv6 server then "[%s]" else "%s") config.addr config.port;
117117
if config.delete then (
118118
S.add_route_handler server ~meth:`DELETE
119-
S.Route.rest
119+
S.Route.rest_of_path_urlencoded
120120
(fun path _req ->
121-
let path = decode_path path in
122121
if contains_dot_dot path then (
123122
S.Response.fail_raise ~code:403 "invalid path in delete"
124123
) else (
@@ -135,7 +134,7 @@ let serve ~config (dir:string) : _ result =
135134
);
136135
if config.upload then (
137136
S.add_route_handler_stream server ~meth:`PUT
138-
S.Route.rest
137+
S.Route.rest_of_path_urlencoded
139138
~accept:(fun req ->
140139
match S.Request.get_header_int req "Content-Length" with
141140
| Some n when n > config.max_upload_size ->
@@ -145,7 +144,6 @@ let serve ~config (dir:string) : _ result =
145144
| _ -> Ok ()
146145
)
147146
(fun path req ->
148-
let path = decode_path path in
149147
let fpath = dir // path in
150148
let oc =
151149
try open_out fpath
@@ -166,9 +164,8 @@ let serve ~config (dir:string) : _ result =
166164
(fun _ _ -> S.Response.make_raw ~code:405 "upload not allowed");
167165
);
168166
S.add_route_handler server ~meth:`GET
169-
S.Route.rest
167+
S.Route.rest_of_path_urlencoded
170168
(fun path req ->
171-
let path = decode_path path in
172169
let full_path = dir // path in
173170
let mtime = lazy (
174171
try Printf.sprintf "mtime: %f" (Unix.stat full_path).Unix.st_mtime

0 commit comments

Comments
 (0)