【问题标题】:Mounting Suave in an Owin application在 Owin 应用程序中安装 Suave
【发布时间】:2016-12-20 14:27:47
【问题描述】:

我有一个用 C# 编写的现有 owin 应用程序,并希望将一个 suave 应用程序作为中间件安装,但由于我对 F# 比较陌生,我发现很难导航应该如何完成。我想我正在寻找类似的东西:

// 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())

至于魔法应该是什么,我认为它是OwinApp.ofAppFuncOwinApp.ofMidFunc 的组合,但我终其一生都无法弄清楚它应该是什么。

【问题讨论】:

    标签: f# owin suave


    【解决方案1】:

    没有简单的魔法。1ofAppFuncofMidFunc 在这里用于使用 OWIN 组件创建 WebParts,即 OWIN -> Suave,而您想要 Suave -> OWIN .

    以下内容适用于您的“应用程序”,并作为示例使其正常工作:

    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>)
    

    主要工作委托给withCtx,它试图满足给定IOwinContextWebPart的请求。它主要通过在 Suave 和 OWIN 上下文和相关实体之间来回转换来实现。 请注意,此代码是 PoC(概念验证)并且不适合生产。 如果 Suave 无法满足请求,SuaveMiddleware 会将请求转发到下一个中​​间件。

    从 C# 中使用很容易:

    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);
            }
        }
    }
    

    给定

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

    两个网址都有效:

    http://localhost:9000/hello

    你好获取

    http://localhost:9000/api

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

    1 至少我不知道。我很高兴被证明是错误的。

    【讨论】:

    • 非常感谢!我将尝试一下,看看我是否可以填补任何空白。
    • 工作愉快,现在我需要传递凭据,我们应该能够使用 suave 部署服务!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2013-01-03
    相关资源
    最近更新 更多