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.
source share