aantron/dream

Difference between path and path/ in the router

Closed this issue ยท 5 comments

Say I have the scope:

Dream.scope "/users" []
  [ Dream.get "/" (fun _ -> Dream.html "Hello!") ]

When I navigate to /users I expect to see Hello! but instead I get a 404. If I navigate to /users/ however, I will see Hello!. I don't think this is intentional.

If I want it to catch without the final slash, I have to add another route to the scope:

Dream.scope "/users" []
  [ Dream.get "/" (fun _ -> Dream.html "Hello!")
  ; Dream.get "" (fun _ -> Dream.html "Hello!")
  ]

Then it is working as expected.

This behavior is intentional -- a final /users is meant to access a "file-like" resource /users relative to / (meaning, relative links will be relative to /), while /users/ is meant to list a directory /users or access /users/index.html (or otherwise, according to the Web app), and relative links will be relative to /users/. There are some discussions of this here. Indeed, Dream has tests ensuring this:

(* Router distinguishes resources and directories. *)
let%expect_test _ =
show "/abc" @@ Dream.router [
Dream.get "/abc/" (fun _ -> Dream.respond "foo");
];
[%expect {|
Response: 404 Not Found |}]
let%expect_test _ =
show "/abc/" @@ Dream.router [
Dream.get "/abc" (fun _ -> Dream.respond "foo");
];
[%expect {|
Response: 404 Not Found |}]

Depending on the app, it may always want to respond in the same way to both, or it may always want to respond with a redirect from one or the other (for SEO purposes or otherwise), so Dream doesn't make a decision about this either way. It should probably be more clearly documented, however. I usually write a middleware for my apps that does "the right thing" for each app. Some of these should probably come with Dream, and there is already an issue about one of them, #125.

I would like to leave this issue open as a documentation issue. Thanks!

No problem, thanks for getting back to me. It does make sense.

We can probably add text like "Note that path and path/ are different routes in HTTP" to the documentation of Dream.router. However, I'd like to hyperlink from that sentence to a good resource explaning the difference.

So far, we have the SO discussion I found and linked earlier, but if anyone can suggest something better, I would be very happy to use it (or please open a PR with it directly!).

@aantron If you'd like I can take a crack at writing some documentation, just not sure where you'd like it :)

Thank you. I think somewhere around here should work.