2017-03-29 1 views
0

私は、レスポンスのコンテンツタイプがtext/htmlなら、私は見ることができるクリスタル(特にケマル)用のツールを書こうとしています。 HTTP::Responseに書き込まれてから、HTML要素を既存のhtml応答本体に挿入してクライアントに送信されます。HTTP :: Responseが書かれた後に変更する方法

HTTP::Server::Responseは書き込み専用ですが、Gzip::Writerのようなものは本文を変更することができます。

HTTP::Server::Response html本文がクライアントに送信される前に変更するにはどうすればよいですか?

+0

私はこれを試していませんが、 'env.response.write("

test
".to_slice)'は動作しますか? - [api link](https://crystal-lang.org/api/0.21.1/HTTP/Server/Response.html#write%28slice%3ABytes%29-instance-method) – fridgerator

+0

質問を更新するだけです。私はすでにHTMLレスポンス本体に書き込まれているhtmlコンテンツを変更したいと思います。 –

答えて

1

これはCrystalで書かれていますので、他の人たちのやり方に関する情報源を見てみましょう。

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

は、どのように我々が書き込まれているの応答を変更することを利用することができます:

例としてCompressHandlerを取ると、基本的な考え方は、所望の制御が可能なものと応答のIOを交換することです?

ナイーブ(と遅い)の例では、単に元の出力のホールドを維持し、代わりに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::SizedおよびIO::MultieWriterの中で見つけることができ、パターンは、不要な割り振りを防止するために実際には一般的です。

+0

スマートなソリューションのPoCで楽しい時を過ごしたことはありますか?おそらくバグがありません。https://gist.github.com/jhass/abf9a29c6309add414e2b852ac0fff69 –

+0

2番目の解決方法では、コンテンツタイプがHTMLとして設定されているかどうかわかりません。右? –

+0

本文の前にヘッダを書かなければならない場合、おそらく渡して 'context.headers'を見て、それに基づいてプロキシとアクティブモードとを切り替えることができます。 –

関連する問題