LoginSignup
1
1

More than 5 years have passed since last update.

特定ホスト に対する HTTP リクエスト・レスポンスをコピーする proxy 類似 HTTPサーバ

Posted at

特定ホストしか使えないので、http proxy ではない何か
Web API の、API Base を変えて遊ぶときに使えるかも (https の通信内容を見るよりは容易?)
以下の例では、mackerel.io の mackerel-agent で apibase = "http://localhost:4567" という設定をするとそのまま使える

require 'sinatra'
require 'net/http'
require 'uri'
require 'pathname'
require 'logger'
require 'pp'

mackerel = 'https://mackerel.io'
mackerel_url = URI.parse(mackerel)

logdir = Pathname.new(__FILE__).parent + 'log'
logdir.directory? || logdir.mkpath
logfile = logdir + Time.now.strftime('%Y-%m-%d')
logio = logfile.open('a')
logger = Logger.new(logio)

[:get, :post, :delete, :patch, :put, :head, :options].each do |method|
  send method, '*' do
    path_with_query = request.env['REQUEST_PATH']
    if request.env['rack.request.query_string'] && request.env['rack.request.query_string'] != ''
      path_with_query << '?' + request.env['rack.request.query_string']
    end

    server_req = Net::HTTP.const_get(request.env['REQUEST_METHOD'].downcase.capitalize).new(path_with_query)
    if body = env["rack.input"].gets
      server_req.body = body

      if request.env['CONTENT_TYPE'] = 'application/json'
        logger << [Time.now.strftime('%Y-%m-%d %H:%M:%S'), path_with_query, body].join("\t")
        logio.flush
      end
    end

    http_headers = request.env.select { |k, v| k.start_with?('HTTP_') }
    headers = http_headers.inject({}) do |a, (k, v)|
      a[k.sub(/^HTTP_/, "").downcase.gsub(/(^|_)\w/) { |word| word.upcase }.gsub("_", "-") ] = v
      a
    end
    headers.each do |key, val|
      server_req.add_field(key, val)
    end

    # special Header
    server_req['HOST'] = mackerel_url.host
    server_req['Content-Type'] = request.env['CONTENT_TYPE']

    http = Net::HTTP.new(mackerel_url.host, mackerel_url.port)
    if mackerel_url.scheme == 'https'
      http.use_ssl = true
    end

    server_resp = nil
    http.start do |h|
      server_resp = h.request(server_req)
    end

    server_resp.each do |key, val|
      response[key] = val
    end
    response.header.delete('content-length')

    status server_resp.code
    return server_resp.body
  end
end
1
1
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
1
1