Kemal кэширует ответы с помощью промежуточного программного обеспечения обработчика

Kemal кэширует ответы с помощью промежуточного программного обеспечения обработчика

Я пытаюсь сделать кэширование некоторого запроса GET с Kemal.

class CachingHandler < Kemal::Handler

    property cache : Hash(String, IO::Memory)

    def initialize
        @cache = Hash(String, IO::Memory).new
    end

    def call(context)
        puts "Caching"
        puts "Key: #{ context.request.resource }"
        if output = @cache[context.request.resource]?
            puts "Cache: true"
            IO.copy output, context.response.output
        else
            puts "Cache: false"
            puts "Cache: building"
            context.response.output          =
            @cache[context.request.resource] = IO::Memory.new
            # continue
            puts "Cache: continue"
            call_next context
        end
    end
end

Но в первом запросе браузер всегда ждет ответа. А во втором запросе отправить ошибку "Закрытый поток (IO::Error)".

1 ответ

Вы косвенно устанавливаете context.response.output в IO::Memory.new, Таким образом, следующий обработчик будет записывать не в выходной поток соединения, а в память ввода-вывода.

Вам нужно будет скопировать данные потока в память и сокет. Может быть IO::MultiWriter может помочь с этим, как response.output = IO::MultiWriter.new(response.output, memory_io),

Кроме того, я бы рекомендовал не хранить IO::Memory случаи, а скорее их необработанные данные как Bytes (io.to_slice). После того, как вы поместите его в кеш, больше нет смысла в IO. Вы можете просто записать байты непосредственно в выходной поток при попадании в кеш (response.write(bytes).

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