0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

webrickでproxyを作ったときレスポンスのbodyが文字列として取り出せない

Posted at

ちょっと悩んだのでメモ。

あるWebアプリがどんなパラメータの受け渡しをしてるのか覗いてやろうと思って WEBrick::HTTPProxyServer でプロキシサーバを作りました。その時レスポンスのボディ (WEBrick::HTTPResponse オブジェクト) がなんか Proc オブジェクトになってたので中身が覗けません…。で、こういうふうにやれば覗けましたというメモです。

だめな例

s = WEBrick::HTTPProxyServer.new(
      Port: 8080,
      ProxyContentHandler: ->(_req, res) {
        puts res.body # ここが問題。これじゃ覗けない
      })
Signal.trap('INT') do
  s.shutdown
end
s.start

だめな例では #<Proc:0x00007f8a06977628 (省略)/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/webrick-1.7.0/lib/webrick/httpproxy.rb:344 (lambda)> とか言う文字列が出力されます。

res.body の中身を見るとなんかパラメータを一個取り (xとします) bodyを保持しているバッファ (body_tmp: 実体は Array) からから読み出して x に write で書いていたので StringIO オブジェクトを渡してやればいいかなと思ってこうしました。

良い例

s = WEBrick::HTTPProxyServer.new(
      Port: 8080,
      ProxyContentHandler: ->(_req, res) {
        sio = StringIO.new(String.new, 'r+')
        res.body.(sio)
        sio.rewind
        res.body = sio.read
        puts res.body
      })
Signal.trap('INT') do
  s.shutdown
end
s.start

これで body が見えました。res.body に読んだ結果を改めて代入しているのは、こうしないと UA 側に body が渡らないからです (body_tmp.shift で破壊的に読み出してるので残らない)。

あともう一つ、StringIO オブジェクトを作るときに '' などリテラルではなく String.new を渡している理由を説明します。今どき

# frozen_string_literal: true

を普通にやってると思うんですが、これだとリテラルで作った String が freeze されてるので書けないんですよ。ということで 'r+' モードで作ろうとしても permission denied になっちゃいます (よくできてる)。ということで freeze されてない String オブジェクトを得るのに手っ取り早い方法が String.new なのでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?