我正在尝试使用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 ::错误)”错误。
答案 0 :(得分:2)
您间接地将context.response.output
设置为IO::Memory.new
。因此,下一个处理程序不会写入连接的输出流,而是写入内存IO。
您需要将流数据复制到内存和套接字。也许IO::MultiWriter
可以帮助解决这个问题,例如response.output = IO::MultiWriter.new(response.output, memory_io)
。
此外,我建议不要存储IO::Memory
个实例,而应将其原始数据存储为Bytes
(io.to_slice
)。一旦你把它放在缓存中,再也没有IO了。您可以在命中缓存(response.write(bytes
)时直接将字节写入输出流。