0

我正在尝试为 Crystal(特别是 Kemal)编写一些工具,在其中我可以查看响应内容类型是否为text/html并修改已经写入的响应正文,HTTP::Response然后通过将 HTML 元素注入到客户端将其发送到客户端现有的 html 响应正文。

我注意到这HTTP::Server::Response是只写的,但是Gzip::Writer可以修改正文之类的东西。

如何在将HTTP::Server::Responsehtml 正文发送到客户端之前对其进行修改?

4

1 回答 1

1

它是用 Crystal 编写的,所以让我们看看其他人如何做到这一点的源代码。

CompressHandler为例,基本思想是将响应的 IO 替换为允许所需控制的东西:

context.response.output = Gzip::Writer.new(context.response.output, sync_close: true)
# ...
call_next(context)

那么我们如何利用它来修改正在编写的响应呢?

一个天真的(而且很慢)的例子是只保留原始输出并提供一个IO::Memory代替:

client = context.response.output
io = IO::Memory.new
context.response.output = io

call_next(context)

body = io.to_s
new_body = inject_html(body)
client.print new_body

当然,只有当这个处理程序出现在任何将响应转换为非明文的处理程序之前(如上面的CompressHandler),这才会起作用。

一个更聪明的解决方案将提供一个自定义 IO 实现,它只包装原始 IO,观察写入的内容并在正确的位置注入它想要注入的任何内容。此类包装 IO 的示例可以在 中找到,IO::Delimited除其他外,该模式非常常见,可以防止不必要的分配。IO::SizedIO::MultieWriter

于 2017-03-29T20:19:49.620 回答