|
# -*- coding: utf-8 -*- |
|
require 'active_record' |
|
require 'json' |
|
require 'nokogiri' |
|
ActiveRecord::Base.establish_connection({ |
|
'host' => 'localhost', |
|
'user' => 'root' |
|
'password' => '', |
|
|
|
}) |
|
class Mockery < ActiveRecord::Base |
|
class QueryArg <ActiveRecord::Base |
|
belongs_to :mockery |
|
end |
|
class JSONPath <ActiveRecord::Base |
|
belongs_to :mockery |
|
end |
|
class XPath < ActiveRecord::Base |
|
belongs_to :mockery |
|
end |
|
class Header < ActiveRecord::Base |
|
belongs_to :mockery |
|
end |
|
class FormField < ActiveRecord::Base |
|
belongs_to :mockery |
|
end |
|
end |
|
|
|
# Mockery.create(:http_method => 'GET|POST', :path => '/[0-9]+/', |
|
# :http_code => '500', :body => '{some_json:"1"}', :headers_json => |
|
# '{"content-type": "application/json"}') |
|
class Mockery < ActiveRecord::Base |
|
has_many :query_args |
|
has_many :json_paths |
|
has_many :x_paths |
|
has_many :headers |
|
has_many :form_fields |
|
def self.match(env) |
|
search_path = [:http_method_and_path, :query_args, :json, :xml, :form, :headers] |
|
base_query = self.includes([:query_args,:json_paths,:x_paths,:headers,:form_fields]) |
|
scope = search_path.inject(base_query) do |acc,field| |
|
self.send("#{field}_scope", env, acc, field) |
|
end |
|
scope.last |
|
end |
|
|
|
def response |
|
headers = {} |
|
begin |
|
headers = JSON.parse(headers_json) if headers_json |
|
rescue JSON::ParseError => e |
|
ActiveRecord::Base.logger.error(["headers_json", self.id,e.class.to_s, e.message, e.backtrace].to_s) |
|
end |
|
[http_code, body, headers] |
|
end |
|
|
|
def self.http_method_and_path_scope(env,scope, field) |
|
found = scope.where(:http_method => env['request.http_method'], :path => nil) |
|
return found.all unless found.empty? |
|
# I wonder if this works. |
|
found = scope.where(['? rlike http_method and'+ |
|
'? rlike path', |
|
env['request.http_method'], |
|
env['request.path'] |
|
]) |
|
found.all |
|
end |
|
|
|
def self.query_args_scope(env,scope,field) |
|
args = Hash[URI.decode_www_form(env['query_string'])] |
|
#ary = ::decode_www_form(“a=1&a=2&b=3”) |
|
#p ary #=> [[‘a’, ‘1’], [‘a’, ‘2’], [‘b’, ‘3’]] |
|
#p ary.assoc(‘a’).last |
|
#=> ‘1’ |
|
#p ary.assoc(‘b’).last #=> ‘3’ |
|
#p ary.rassoc(‘a’).last #=> ‘2’ |
|
#p Hash[ary] # => {“a”=>“2”, “b”=>“3”} |
|
|
|
scope.select{|i| |
|
i.query_args.all?{|arg| args.has_key?(arg.name)} |
|
} |
|
end |
|
|
|
# JSONPath.create({:path => 'a.b.1.d', :value => '"some_json_value"'}) |
|
def self.json_scope(env,scope,field) |
|
return scope unless env['content-type'] =~ %r{application/json} |
|
json = nil |
|
|
|
begin |
|
json = JSON.parse(Rack::Request.new(env).body) |
|
rescue JSON::ParseError => e |
|
ActiveRecord::Base.logger.error([e.class.to_s, e.message, e.backtrace].to_s) |
|
end |
|
return scope unless json |
|
scope.select do |i| |
|
i.json_paths.all? do |json_path| |
|
value = nil |
|
begin |
|
value = JSON.parse(json_path.value) |
|
rescue JSON::ParseError => e |
|
ActiveRecord::Base.logger.error(["json_path:",json_path.id,e.class.to_s, e.message, e.backtrace].to_s) |
|
end |
|
|
|
curr = json; |
|
json_path.path.split('.').all? do |j| |
|
has = curr.has_key?(j); |
|
next false unless has; |
|
curr = curr[j] |
|
next true |
|
end && |
|
curr == value |
|
end |
|
end |
|
end |
|
# XPath.create(:path => '//some[shit]', :value => "<SomeXML/>") |
|
def self.xml_scope(env,scope,field) |
|
return scope unless env['content-type'] =~ %r{application/xml} |
|
|
|
xml = nil |
|
|
|
begin |
|
xml = Nokogiri::XML.parse(Rack::Request.new(env).body) |
|
rescue Nokogiri::SyntaxError => e |
|
ActiveRecord::Base.logger.error(["nokogiri:",Rack::Request.new(env).body,e.class.to_s, e.message, e.backtrace].to_s) |
|
end |
|
return scope unless xml |
|
|
|
scope.select do |i| |
|
i.x_paths.all? do |x_path| |
|
xml.search(x_path.path).to_xml == x_path.value |
|
end |
|
end |
|
end |
|
# FormField.create(:field => 'some[crap]', :value => 'some other crap') |
|
def self.form_scope(env,scope,field) |
|
req = Rack::Request.new(env) |
|
return scope unless req.form_data? |
|
form = URI::decode_www_form(req.body) |
|
scope.select do | i| |
|
i.form_fields.all? do |form_field| |
|
form[form_field.field] == form_field.value |
|
end |
|
end |
|
end |
|
# Header.create(:name => 'Authorization', :value => "YourMom WW91ciBtb3RoZXIgaXMgcm90dW5kLg==") |
|
def self.headers_scope(env,scope,field) |
|
scope.select do |i| |
|
i.headers.all? do |header| |
|
env[header.name] == header.value |
|
end |
|
end |
|
end |
|
end |
@anachronistic I had some ideas in here. But they can only be discussed in hushed tones over beers.