1

Kemal 使用处理程序中间件缓存响应

我正在尝试使用 Kemal 缓存一些 GET 请求。

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)”错误。

4

1 回答 1

2

您间接设置context.response.outputIO::Memory.new. 因此,下一个处理程序不会写入连接的输出流,而是写入内存 IO。

您需要将流数据复制到内存套接字。也许 aIO::MultiWriter可以帮助解决这个问题,比如response.output = IO::MultiWriter.new(response.output, memory_io).

此外,我建议不要将IO::Memory实例存储为 (),而是将其原始数据存储为Bytes( io.to_slice)。一旦你把它放在缓存中,再有一个 IO 就没有意义了。当缓存被命中时,您可以直接将字节写入输出流(response.write(bytes)。

于 2017-11-05T13:41:47.213 回答