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

Но это не правильно. Я хотел бы использовать стандартные HttpHandlers из модуля ResponseCaching для установки правильных заголовков кэша:

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

Как мне этого добиться?

2 ответа

Я нашел решение своей проблемы.

Да, я могу связать HttpHandlers, как упоминали Джерард и Хонза Брестан, с помощью оператора fish (>=>). Причина, по которой я не смог сделать эту работу, была в том, что я также создал оператора по Result введите открытый модуль. В основном я создал правильный рыбный суп

Как только я реорганизовал свой код, чтобы модуль, содержащий Result Оператор рыбной ловли не был открыт в этой области, все работало нормально, как и ожидалось.

Еще один момент, о котором следует помнить, это то, что кеширование ответов должно вызываться до финализации HttpHandler, иначе оно не будет вызвано:

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

Предполагается, что обработчик кэша ответов должен быть передан в обычный конвейер. Ваш выбор между Ok а также Error это функция выбора, так что вы можете использовать выбор, который принимает список обработчиков, которые могут быть предприняты. Чтобы отклонить путь, просто верните task { return None }, чтобы двигаться вперед, это next ctx,

Если вы хотите сохранить всю логику в одном контроллере, как сейчас, просто сохраните соответствие и направьте свой ответ json/text в один из обработчиков кэширования.

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

если он вложен в Hander, а не в конвейер, вы должны применить next & ctx

Другие вопросы по тегам