F#长颈鹿:基于结果的不同缓存头

时间:2018-12-14 14:08:43

标签: f# f#-giraffe

我正在努力根据结果是正常还是错误来设置不同的缓存响应标头。我的代码类似于以下内容(但结果中包含其他类型):

let resultToJson (result:Result<'a,string>) : HttpHandler = 
    match result with
    | Ok o -> Successful.ok (json o)
    | Error s -> ServerErrors.internalError (text s)

我可以通过执行以下操作来添加标题:

let resultToJson (result:Result<'a,string>) : HttpHandler = 
    fun (next : HttpFunc) (ctx : HttpContext) ->
        let response =
            let headers = ctx.Response.Headers
            match result with
            | Ok o ->
                headers.Add("Cache-Control", new StringValues("public, max-age=10, stale-while-revalidate=2"))
                headers.Add("Vary", new StringValues("Origin"))
                Successful.ok (json o)
            | Error s -> 
                headers.Add("Cache-Control", new StringValues("no-cache"))
                ServerErrors.internalError (text s)
        response next ctx

但这感觉不对。我想使用ResponseCaching模块中的标准HttpHandlers来设置正确的缓存头:

publicResponseCaching 10 (Some "Origin") // For Ok: Add 10 sec public cache, Vary by Origin
noResponseCaching // For Error: no caching

我该如何实现?

2 个答案:

答案 0 :(得分:0)

应该将response cache handler用管道传输到普通管道。您可以在OkError之间进行选择,这是一个select函数,因此您可以使用一个选择,该选择带有可以尝试的处理程序列表。要拒绝路径,只需返回task { return None },然后返回next ctx

如果您想像现在一样将所有逻辑保留在一个控制器中,只需保持匹配并将json / text响应通过管道传递到一个缓存处理程序中即可。

let fn = json o >=> publicResponseCaching 30 None) in fn next ctx

如果它嵌套在处理程序中而不是嵌套在管道中,则必须应用nextctx

答案 1 :(得分:0)

我找到了解决问题的方法。

是的,我可以使用fish运算符(>=>)像Gerard和Honza Brestan所述链接HttpHandler。我之所以不能进行这项工作,是因为我还为打开的模块中的Result类型创建了一个fish操作符。基本上我已经制作了合适的鱼汤

我重构代码以使包含Result fish运算符的模块无法在此范围内打开时,一切工作正常。

要记住的另一点是,在终结HttpHandler之前,必须先将响应缓存称为 ,否则将不被调用:

// Simplified code
let resultToJson =
    function
    | Ok o -> publicResponseCaching 10 (Some "Origin") >=> Successful.ok(json o)
    | Error e -> noResponseCaching >=> ServerErrors.internalError(text e)