team-rf
team-rf

Reputation: 241

How to stop routing with an error

I'm writing a Suave app and I want to stop if the origin ip is not in the authorized list for the route. For this I've written a small filter:

let RemoteIp (ipList: System.Net.IPAddress List) (x: Http.HttpContext) = 
    if (ipList |> List.map (fun ip -> x.clientIpTrustProxy.Equals ip ) |> List.contains true)
    then
        async.Return (Some x)
    else
        async.Return None

Then I fiter out with

        Filters.path "/cache" >=> RemoteIp authorizedIps >=> Filters.GET >=> Successful.OK ""

so I get to process the call only if it comes from an IP in my authorized list, if not it just continues. However what I really want to do is to return 403. Right now I'm just short circuiting the route search.

Is there anything like a branch combinator?

Upvotes: 1

Views: 42

Answers (1)

team-rf
team-rf

Reputation: 241

I endend writing a Branch function:

let Branch (x:WebPart) (y:WebPart) (z:WebPart): WebPart =
fun arg -> async {
   let! res = x arg 
   match res with
   | Some v -> return! y arg
   | None -> return! z arg
}

So now I have something like

Filters.path "/cache" >=> Branch (RemoteIp authorizedIps) (Successful.OK "Yea!") (RequestErrors.FORBIDDEN "Nope")

It might come handy sometime, but really, what I should have thought of before is Fyodor's suggestion, which I think is more readable:

        Filters.path "/cache" >=> choose [
           RemoteIp authorizedIps >=> Successful.OK "Yea!"
           RequestErrors.FORBIDDEN "Nope"
        ]

Upvotes: 2

Related Questions