Install Suave in the Owin app

I have an existing owin application written in C # and I would like to install a reliable application as middleware, but since I'm relatively new to F #, I find it difficult to navigate how this should be done. I think I'm looking for something like:

// in F# land module MySuaveApp.ApiModule let app = choose [ GET >=> choose [ path "/hello" >=> OK "Hello GET" path "/goodbye" >=> OK "Good bye GET" ] POST >=> choose [ path "/hello" >=> OK "Hello POST" path "/goodbye" >=> OK "Good bye POST" ] ] let getSuaveAsMiddleware() = ... magic goes here ... // in Startup.cs app.Use(MySuaveApp.ApiModule.getSuaveAsMiddleware()) 

As for this magic, I think it is a combination of OwinApp.ofAppFunc or OwinApp.ofMidFunc , but I canโ€™t understand for a living what it should be.

+5
source share
1 answer

There is no easy magic. 1 ofAppFunc and ofMidFunc here for creating WebPart from WebPart components, i.e. OWIN โ†’ Suave, whereas you want Suave โ†’ OWIN.

The following works for your โ€œapplicationโ€ and serves as an example of what is needed for it to work:

 open System.Runtime.CompilerServices [<Extension>] module Api = open Suave open Successful open Filters open Operators open Microsoft.Owin open System.Threading.Tasks let app = choose [ GET >=> choose [ path "/hello" >=> OK "Hello GET" path "/goodbye" >=> OK "Good bye GET" ] POST >=> choose [ path "/hello" >=> OK "Hello POST" path "/goodbye" >=> OK "Good bye POST" ] ] let withCtx (ctx : IOwinContext) webpart = async { let request = { HttpRequest.empty with headers = ctx.Request.Headers |> List.ofSeq |> List.map (fun kvp -> kvp.Key, kvp.Value |> String.concat ",") host = ctx.Request.Host.Value ``method`` = HttpMethod.parse ctx.Request.Method url = ctx.Request.Uri } let! res = webpart { HttpContext.empty with request = request } res |> Option.iter (fun r -> ctx.Response.StatusCode <- r.response.status.code match r.response.content with | Bytes bs -> ctx.Response.Write bs | _ -> failwith "Not supported") return res } type SuaveMiddleware(n) = inherit OwinMiddleware(n) override __.Invoke(context : IOwinContext) = let res = withCtx context app |> Async.RunSynchronously match res with | Some _ -> Task.CompletedTask | None -> base.Next.Invoke context [<Extension>] let UseSuave(app : Owin.IAppBuilder) = app.Use(typeof<SuaveMiddleware>) 

The main work is delegated to withCtx , which attempts to fulfill a request with IOwinContext and WebPart . It does this mainly by transforming back and forth between the Suave and OWIN context and the objects associated with it. Please note that this code is PoC (Proof-of-Concept) and is not suitable for production . Request SuaveMiddleware ahead for the next middleware if Suave cannot complete the request.

Using with C # is easy:

 using MySuave; using Owin; namespace Main { using System.Web.Http; public class Startup { public static void Configuration(IAppBuilder appBuilder) { appBuilder.UseSuave(); var config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); appBuilder.UseWebApi(config); } } } 

given

 namespace Main.Example { using System.Web.Http; [RoutePrefix("api")] public class ExampleController : ApiController { [HttpGet, Route("")] public string Index() { return "Hello World"; } } } 

And both URLs work:

http://localhost:9000/hello

Hi get

http://localhost:9000/api

  <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string> 

1 At least I don't know. I am happy that I was mistaken.

+5
source

All Articles