Help us understand the problem. What is going on with this article?

クライアントからやってくる本物のHTTPリクエストをダンプする

More than 5 years have passed since last update.

Rack限定ならむかし rack-spyup というものを書いた。自分で使ってみたけどJSON APIのデバッグとかだと革命的に便利だと思う。

ただ、Rackに到達する前にリクエストがお亡くなりになったりとか、そもそもサーバルビーじゃないしとかあると思うので、もっと汎用的な感じでダンプする手順をメモしてみる。

リクエストが来たら内容を全部ダンプするHTTPサーバを作る

Rubyに標準添付されている、WEBrickの基本的な機能で割と簡単に作れる。

http-dumper.rb
# -*- coding: utf-8 -*-
require 'optparse'
require 'webrick'
require 'json'
options = ARGV.getopts("p:", "port:")

# The :monkey: raises
# cf. http://d.hatena.ne.jp/vividcode/20110505/1304618393
class WEBrick::HTTPServlet::ProcHandler
  alias do_PUT    do_POST
  alias do_DELETE do_POST
end

HORIZON = "\e[31m" + ("#" * 72) + "\e[0m"

def dump_http_request(req)
  puts HORIZON
  puts req.request_line
  puts req.raw_header
  puts
  if body = req.body
    puts body.lines.map{|line| line.gsub /[[:cntrl:]]/, '' }
  else
    puts "\e[35m*** Empty request body (maybe it is GET) ***\e[0m"
  end
  puts HORIZON
  puts
end

srv = WEBrick::HTTPServer.new(
  :BindAddress => "0.0.0.0",
  :Port => (options["p"] || options["port"] || raise("Need option -p=PORT")).to_i,
)

srv.mount_proc "/" do |req, res|
  dump_http_request(req)

  res.content_type = "application/json"
  res.body = {return: "OK"}.to_json
end

Signal.trap('INT') { srv.shutdown }
srv.start

dump_http_request が冗長だが(しょうがない)、WEBrick自体は簡単に扱えることが分かると思う。

これをターミナル(1)で起動しとく:

$ ruby http-dumper.rb  -p 3002

リクエストをクローンして二つのサーバに送りつけるひとを作る

かっこ良くGoの gor を使おうとしたが、Macだとちゃんと動かない感じがする。

今回は手軽さ重視で kage を使い、gorコマンドと同じようなことをさせてみる。 gem install kage した後:

kage-front.rb
require 'optparse'
require 'kage'

options = ARGV.getopts("p:", "port:", "backend-port:", "dumper-port:")

Kage::ProxyServer.start do |server|
  server.port = (options["p"] || options["port"] || raise("Need option -p=PORT")).to_i
  server.host = '0.0.0.0'
  server.debug = false

  server.add_master_backend(:dev, 'localhost', options["backend-port"])
  server.add_backend(:dump, 'localhost', options["dumper-port"])

  server.on_select_backends do |request, headers|
    # アセットまでdump serverに送るのはうざったいので適当に振り分ける
    is_asset = request[:path] =~ /\.(ico|js|css|gif|png|jpe?g)$/
    is_asset ? [:dev] : [:dev, :dump]
  end

  puts "Server is listening 0.0.0.0:#{server.port}"
end

これもターミナル(2)で立ち上げ。

$ ruby kage-front.rb -p 3000 --backend-port=3001 --dumper-port=3002

あとは分かるな

検査したいアプリを 3001 番ポートでターミナル(3)に立ち上げること。Railsなら rails s -p 3001

アクセスする

http://localhost:3000 にいつも通りアクセスする。そうすると、いつも通りのウェブサービスが見える...

一方で、ターミナル(1)ではリクエストの内容がダンプされているのであった!

httpdump.png

Usage

普通HTTPリクエストがそもそも壊れてるって少ないと思うけど、今回はジャバを触っていたらどうも壊れてしまっていたのでこういう感じでチェックしていた。参考にしてください。

ブラウザならデベロッパツールでいいけど、HTTPってやっぱいろんなクライアントから叩くと思うんで...。

FAQ

ngrep でいいじゃん

そうですね。tcpflowも便利でいいですね。

ただまあ、一応、そもそも「HTTPリクエストをクローンする」というのが便利かなと思ったのでメモがてら書いてみた感じでござる。あと、APIならともかくWebサービスだとアセットへのアクセスも全部出てしまってノイズっぽいし、このやりかただと正規表現などで適当に絞れると思う。

追記

gemの形でインストールできるようにした ので、bundlerなど使って入れてみて利用できるようになりました(rubygems.org には置かない予定です)。

udzura
投稿しているコードは、指定が無い限り MIT とします。
http://udzura.hatenablog.jp
pepabo
「いるだけで成長できる環境」を標榜し、エンジニアが楽しく開発できるWebサービス企業を目指しています。
https://pepabo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした