Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSharper - Is there a simple way to catch "not found" routes?

Tags:

f#

websharper

Is there a simple way of using Sitelets and Application.MultiPage to generate a kind of "default" route (to catch "not found" routes, for example)?

Example

type EndPoint =
    | [<EndPoint "/">] Home
    | [<EndPoint "/about">] About


[<Website>]
let Main =
    Application.MultiPage (fun ctx endpoint ->
        match endpoint with
        | EndPoint.Home -> HomePage ctx
        | EndPoint.About -> AboutPage ctx

I would like to define an EndPoint that could handle requests to anything but "/home" and "/about".

like image 205
boechat107 Avatar asked Sep 23 '16 23:09

boechat107


1 Answers

I just published a bug fix (WebSharper 3.6.18) which allows you to use the Wildcard attribute for this:

type EndPoint =
    | [<EndPoint "/">] Home
    | [<EndPoint "/about">] About
    | [<EndPoint "/"; Wildcard>] AnythingElse of string

[<Website>]
let Main =
    Application.MultiPage (fun ctx endpoint ->
        match endpoint with
        | EndPoint.Home -> HomePage ctx
        | EndPoint.About -> AboutPage ctx
        | EndPoint.AnythingElse path -> Content.NotFound // or anything you want
    )

Note though that this will catch everything, even URLs to files, so for example if you have client-side content then urls like /Scripts/WebSharper/*.js will not work anymore. If you want to do that, then you'll need to drop to a custom router:

type EndPoint =
    | [<EndPoint "/">] Home
    | [<EndPoint "/about">] About
    | AnythingElse of string

let Main =
    Application.MultiPage (fun ctx endpoint ->
        match endpoint with
        | EndPoint.Home -> HomePage ctx
        | EndPoint.About -> AboutPage ctx
        | EndPoint.AnythingElse path -> Content.NotFound // or anything you want
    )

[<Website>]
let MainWithFallback =
    { Main with
        Router = Router.New
            (fun req ->
                match Main.Router.Route req with
                | Some ep -> Some ep
                | None ->
                    let path = req.Uri.AbsolutePath
                    if path.StartsWith "/Scripts/" || path.StartsWith "/Content/" then
                        None
                    else
                        Some (EndPoint.AnythingElse path))
            (function
                | EndPoint.AnythingElse path -> Some (System.Uri(path))
                | a -> Main.Router.Link a)
    }

(copied from my answer in the WebSharper forums)

like image 199
Tarmil Avatar answered Nov 15 '22 09:11

Tarmil