F#Giraffe:基于结果的不同缓存头



我很难根据结果是Ok还是Error来设置不同的缓存响应标头。我的代码如下(但结果中有其他类型(:

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

我该如何做到这一点?

响应缓存处理程序应该通过管道连接到普通管道中。您在OkError之间的选择是一个选择函数,因此您可以使用一个包含可以尝试的处理程序列表的选择。要拒绝一条路径,只需返回一个task { return None },要继续前进,它就是next ctx

如果您想像现在这样将所有逻辑保留在一个控制器中,只需保持匹配并将json/文本响应管道传输到其中一个缓存处理程序中。

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

如果它嵌套在hander中,而不是管道中,则必须应用next&ctx

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

是的,我可以使用fish操作符(>=>(来链接Gerard和Honza-Brestan提到的HttpHandlers。我最初无法做到这一点的原因是,我还在一个打开的模块中为Result类型创建了一个fish运算符。基本上,我已经制作了合适的鱼汤

一旦我重构了代码,使包含Resultfish运算符的模块不在此范围内打开,一切都如预期的那样正常。

需要记住的另一点是,响应缓存需要在完成HttpHandler之前调用,否则将不会调用:

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

最新更新