SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
714 stars 108 forks source link

Links.index ends links in slash and requests with trailing slashes result in 404 not found #152

Open MarneeDear opened 5 years ago

MarneeDear commented 5 years ago

Possibly related to issues #126, #108, #111

Windows 10 Saturn 0.7.6 Dotnet SDK 2.1.403

Links/paths are not expected to end in slash, but Links.index ends them in a slash.

If you setup a site with the Saturn template, and follow the user guide, you get a Books resource with the index at /books. If you only follow the guide, requests to /books/ works, but if you customize the router you get a 404 (see my code example below).

I can make Link.index remove the trailing slash but:

When /books/ works:

If you only follow the guide, you will have a browserRouter that looks like this.

    let browserRouter = router {
    not_found_handler (htmlView NotFound.layout) //Use the default 404 webpage
    pipe_through browser //Use the default browser pipeline
    forward "/books" Books.Controller.resource
    forward "" defaultView //Use the default view
}

When /books/ doesn't work

My routing looks like this. In my example code, I wanted to prevent unauthenticated users from accessing the Books resource, so I setup a loggedInView router (you can see the source code here). Using get like this causes a 404 on requests to /books/ .

let login = pipeline {
    requires_authentication (fun next ctx -> htmlView (Login.layout ctx) next ctx)
    //plug print_user_details
}
let loggedInView = router {
    pipe_through login
    pipe_through protectFromForgery
    forward "/books" Books.Controller.resource 
    forwardf "/books/%s" (fun s -> Books.Controller.resource)
let browserRouter = router {
    not_found_handler (htmlView NotFound.layout) //Use the default 404 webpage
    pipe_through browser //Use the default browser pipeline
    forward "" defaultView //Use the default view
    get "/books" loggedInView    
    getf "/books/%s" (fun s -> loggedInView)

Possibly related to issues #126, #108, #111