HTTPアクセスユーティリティ
HTTPアクセスをスタブ風?に行うためのユーティリティを書いてみました。
やりたかったこと
使い方
設定ファイルを書きます。
--- # コンフィグレーション conf: #proxy_host: <プロキシホスト> #proxy_port: <プロキシポート> # デフォルトの接続先設定 # 個別の設定で設定されなかった値は、ここでの指定が使われる。 default: host: www.google.co.jp path: /search port: 80 method: "get" # "post" or "get" headers: # hoo: var # メソッド名に対応する接続先の設定 requests: get_yahoo: # メソッド名 host: yahoo.co.jp path: "" search: params: q: "" # 検索条件
スタブを生成してメソッドを実行します。
require 'http-requestor' # スタブを生成 / 引数で設定ファイルのパスを指定 stub = HttpRequestor.new("./request.yaml") # 設定ファイルの get_yahoo に対応するURLにアクセスし、結果を返す # 戻り値はNet::HTTPResponse response = stub.get_yahoo() puts response.code puts response.body # ブロックを指定して接続先情報をカスタマイズできる。 response = stub.search(){ |request| request["params"]["q"] = "hoo" } puts response.body
実装
require "net/http" require 'yaml' require 'cgi' class HttpRequestor # 初期化する。 def initialize( request_file="./request.yaml" ) File.open( request_file ) {|f| @request = YAML.load( f ) } end # メソッドが定義されていない場合に呼ばれる。 def method_missing( name, *args, &block ) return do_request( name.to_s, &block ) end # リクエストを実行する。 # ブロックが与えられた場合は、ブロックにリクエスト情報を渡し編集する。 def do_request ( method, &block ) fail "unknown method " << method unless @request["requests"].key?( method ) request = merge( {"params"=>{}, "headers"=>{}}, @request["requests"][method] ) request = merge( request, @request["default"] ) block.call( request ) if block_given? response = nil Net::HTTP.version_1_2 requestor = nil if ( @request["conf"] != nil && @request["conf"]["proxy_host"] != nil && @request["conf"]["proxy_port"] != nil ) requestor = Net::HTTP::Proxy(@request["conf"]["proxy_host"], @request["conf"]["proxy_port"]) else requestor = Net::HTTP end requestor.start( request["host"], request["port"] ) { |http| param = map_to_param( request["params"] ) param += "&" + list_to_param(request["param-list"]) if request["method"] == "get" response = http.get( request["path"] + "?" + param, request["headers"] ) elsif request["method"] == "post" # POSTの場合、bodyの指定があればそちらを優先する。 param = request["body"] != nil ? request["body"] : param response = http.post( request["path"], param, request["headers"] ) end } return response end private def map_to_param( map ) return "" if map == nil str = "" map.each { | key, value | str << key << '=' << CGI.escape(value.to_s) << '&' if value != nil } return str end def list_to_param( list ) return "" if list == nil str = "" list.each { | item | if item["key"] != nil && item["value"] != nil str << item["key"] << '=' << CGI.escape(item["value"].to_s) << '&' end } return str end # リクエストの設定をマージする。 def merge (request, parent) return request if ( parent == nil ) request.merge!(parent) { |key, self_val, other_val| if ( key == "headers" || key == "params" ) merge(self_val != nil ? self_val : {}, other_val) else self_val != nil ? self_val : other_val end } return request end end