steam 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +21 -0
- data/README.textile +91 -0
- data/Rakefile +23 -0
- data/TODO +7 -0
- data/lib/core_ext/ruby/array/flatten_once.rb +9 -0
- data/lib/core_ext/ruby/hash/except.rb +11 -0
- data/lib/core_ext/ruby/hash/slice.rb +14 -0
- data/lib/core_ext/ruby/kernel/silence_warnings.rb +8 -0
- data/lib/core_ext/ruby/process/daemon.rb +23 -0
- data/lib/core_ext/ruby/string/camelize.rb +5 -0
- data/lib/core_ext/ruby/string/underscore.rb +5 -0
- data/lib/steam.rb +43 -0
- data/lib/steam/browser.rb +24 -0
- data/lib/steam/browser/html_unit.rb +87 -0
- data/lib/steam/browser/html_unit/actions.rb +176 -0
- data/lib/steam/browser/html_unit/client.rb +74 -0
- data/lib/steam/browser/html_unit/connection.rb +79 -0
- data/lib/steam/browser/html_unit/drb.rb +45 -0
- data/lib/steam/browser/html_unit/matchers.rb +57 -0
- data/lib/steam/browser/html_unit/page.rb +51 -0
- data/lib/steam/browser/html_unit/web_response.rb +116 -0
- data/lib/steam/connection.rb +9 -0
- data/lib/steam/connection/mock.rb +57 -0
- data/lib/steam/connection/net_http.rb +42 -0
- data/lib/steam/connection/open_uri.rb +24 -0
- data/lib/steam/connection/rails.rb +20 -0
- data/lib/steam/connection/static.rb +33 -0
- data/lib/steam/java.rb +74 -0
- data/lib/steam/process.rb +53 -0
- data/lib/steam/request.rb +49 -0
- data/lib/steam/response.rb +13 -0
- data/lib/steam/session.rb +30 -0
- data/lib/steam/session/rails.rb +33 -0
- data/lib/steam/version.rb +3 -0
- data/test/all.rb +3 -0
- data/test/browser/html_unit/actions_test.rb +183 -0
- data/test/browser/html_unit/javascript_test.rb +60 -0
- data/test/browser/html_unit/rails_actions_test.rb +151 -0
- data/test/browser/html_unit_test.rb +97 -0
- data/test/connection/cascade_test.rb +42 -0
- data/test/connection/mock_test.rb +58 -0
- data/test/connection/rails_test.rb +16 -0
- data/test/connection/static_test.rb +14 -0
- data/test/fixtures/html_fakes.rb +191 -0
- data/test/java_test.rb +29 -0
- data/test/playground/connection.rb +19 -0
- data/test/playground/dragdrop_behavior.rb +60 -0
- data/test/playground/drb.rb +55 -0
- data/test/playground/java_signature.rb +22 -0
- data/test/playground/nokogiri.rb +15 -0
- data/test/playground/put_headers.rb +83 -0
- data/test/playground/rack.rb +11 -0
- data/test/playground/rjb_bind.rb +42 -0
- data/test/playground/stack_level_problem.rb +129 -0
- data/test/playground/thread_problem.rb +57 -0
- data/test/playground/web_response_data.rb +21 -0
- data/test/playground/webrat.rb +48 -0
- data/test/playground/xhr_accept_headers.rb +61 -0
- data/test/process_test.rb +55 -0
- data/test/session_test.rb +15 -0
- data/test/test_helper.rb +56 -0
- metadata +135 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# Just hides the ugly Java'ish details of instantiating, configuring and using
|
2
|
+
# a com.gargoylesoftware.htmlunit.WebClient (HtmlUnit's main browser object).
|
3
|
+
|
4
|
+
module Steam
|
5
|
+
module Browser
|
6
|
+
class HtmlUnit
|
7
|
+
class Client
|
8
|
+
Java.load_from(Steam.config[:html_unit][:java_path])
|
9
|
+
|
10
|
+
Java.import 'com.gargoylesoftware.htmlunit.Version'
|
11
|
+
Java.import 'com.gargoylesoftware.htmlunit.WebClient'
|
12
|
+
Java.import 'com.gargoylesoftware.htmlunit.BrowserVersion'
|
13
|
+
Java.import 'com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController'
|
14
|
+
Java.import 'com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException'
|
15
|
+
|
16
|
+
include Java::Com::Gargoylesoftware::Htmlunit
|
17
|
+
|
18
|
+
class SilencingListener
|
19
|
+
def notify(message, origin); end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(connection = nil, options = {})
|
23
|
+
options = Steam.config[:html_unit].merge(options)
|
24
|
+
|
25
|
+
@java = WebClient.new(BrowserVersion.send(options[:browser_version]))
|
26
|
+
@java.setCssEnabled(options[:css])
|
27
|
+
@java.setJavaScriptEnabled(options[:javascript])
|
28
|
+
@java.setPrintContentOnFailingStatusCode(options[:on_error_status] == :print)
|
29
|
+
@java.setThrowExceptionOnFailingStatusCode(options[:on_error_status] == :raise)
|
30
|
+
@java.setThrowExceptionOnScriptError(options[:on_script_error] == :raise)
|
31
|
+
|
32
|
+
self.log_level = options[:log_level]
|
33
|
+
unless options[:log_incorrectness]
|
34
|
+
listener = Rjb::bind(SilencingListener.new, 'com.gargoylesoftware.htmlunit.IncorrectnessListener')
|
35
|
+
@java.setIncorrectnessListener(listener)
|
36
|
+
end
|
37
|
+
|
38
|
+
if options[:resynchronize]
|
39
|
+
controller = NicelyResynchronizingAjaxController.new
|
40
|
+
@java.setAjaxController(controller)
|
41
|
+
end
|
42
|
+
|
43
|
+
if connection
|
44
|
+
connection = Rjb::bind(HtmlUnit::Connection.new(connection), 'com.gargoylesoftware.htmlunit.WebConnection')
|
45
|
+
@java.setWebConnection(connection)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def request(*args)
|
50
|
+
@java.getPage(*args) # TODO use WebRequestSettings
|
51
|
+
end
|
52
|
+
|
53
|
+
def wait_for_javascript(timeout)
|
54
|
+
waitForBackgroundJavaScript(timeout)
|
55
|
+
yield if block_given?
|
56
|
+
end
|
57
|
+
|
58
|
+
# FIXME setLevel throws "Fail: unknown method name `setLevel'". weird.
|
59
|
+
def log_level=(level)
|
60
|
+
[ 'com.gargoylesoftware.htmlunit',
|
61
|
+
'com.gargoylesoftware.htmlunit.html',
|
62
|
+
'com.gargoylesoftware.htmlunit.javascript',
|
63
|
+
'org.apache.commons.httpclient'
|
64
|
+
].each { |classifier|
|
65
|
+
Java.logger(classifier).setLevel(Java.log_level(level)) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def method_missing(method, *args)
|
69
|
+
@java.send(method, *args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# For internal use in Browser::HtmlUnit to hook into HtmlUnit's request process.
|
2
|
+
# Does not support the Rack interface because HtmlUnit doesn't. Not currently
|
3
|
+
# used by Steam, but potentially useful to get HtmlUnit and the app running in
|
4
|
+
# a single stack.
|
5
|
+
#
|
6
|
+
# Can be set to a com.gargoylesoftware.htmlunit.WebClient like this:
|
7
|
+
#
|
8
|
+
# mock = Steam::Connection::Mock.new
|
9
|
+
# mock.mock :get, 'http://localhost:3000/', 'body!'
|
10
|
+
# connection = Steam::Browser::HtmlUnit::Connection.new(mock)
|
11
|
+
#
|
12
|
+
# client = java::WebClient.new(Java::Com::Gargoylesoftware::Htmlunit::BrowserVersion.FIREFOX_3)
|
13
|
+
# client.setWebConnection(Rjb::bind(connection, 'com.gargoylesoftware.htmlunit.WebConnection'))
|
14
|
+
|
15
|
+
require 'thread'
|
16
|
+
require 'rack/utils'
|
17
|
+
|
18
|
+
module Steam
|
19
|
+
module Browser
|
20
|
+
class HtmlUnit
|
21
|
+
class Connection
|
22
|
+
@@lock = Mutex.new
|
23
|
+
|
24
|
+
Java.import 'com.gargoylesoftware.htmlunit.Version'
|
25
|
+
|
26
|
+
include Java::Com::Gargoylesoftware::Htmlunit
|
27
|
+
|
28
|
+
Java.import('com.gargoylesoftware.htmlunit.MockWebConnection')
|
29
|
+
classifier = Version.getProductVersion == '2.6' ?
|
30
|
+
'org.apache.commons.httpclient.NameValuePair' : # HtmlUnit 2.6
|
31
|
+
'com.gargoylesoftware.htmlunit.util.NameValuePair' # HtmlUnit 2.7
|
32
|
+
NameValuePair = Java.import(classifier, :NameValuePair)
|
33
|
+
|
34
|
+
attr_reader :connection, :java
|
35
|
+
|
36
|
+
def initialize(connection)
|
37
|
+
@connection = connection
|
38
|
+
@java = MockWebConnection.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def getResponse(request)
|
42
|
+
# FIXME preserve original scheme, host + port
|
43
|
+
method = request.getHttpMethod.toString.dup
|
44
|
+
url = request.getUrl.toString.dup
|
45
|
+
|
46
|
+
body = request.getRequestBody
|
47
|
+
body = body.toString.dup if body
|
48
|
+
|
49
|
+
params = request.getRequestParameters
|
50
|
+
params = Hash[*params.toArray.map { |e| [e.name, e.value] }.flatten]
|
51
|
+
|
52
|
+
input = body ? body : Rack::Utils.build_nested_query(params)
|
53
|
+
env = Request.env_for(url, :method => method, :input => input)
|
54
|
+
|
55
|
+
status, headers, response = connection.call(env)
|
56
|
+
response.body.close if response.body.respond_to?(:close)
|
57
|
+
|
58
|
+
set_response(request.getUrl, response)
|
59
|
+
java.getResponse(request)
|
60
|
+
rescue Exception => e
|
61
|
+
puts "#{e.class.name}: #{e.message}"
|
62
|
+
e.backtrace.each { |line| puts line }
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_response(url, response)
|
66
|
+
body = response.body.join
|
67
|
+
status = response.status
|
68
|
+
message = Rack::Utils::HTTP_STATUS_CODES[status.to_i]
|
69
|
+
charset = Steam.config[:charset]
|
70
|
+
headers = response.header.map { |key, value| NameValuePair.new(key, value) }
|
71
|
+
headers = Java::Util::Arrays.asList(headers)
|
72
|
+
content_type = response.content_type
|
73
|
+
|
74
|
+
java.setResponse(url, body, status, message, content_type, charset, headers)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'drb'
|
2
|
+
|
3
|
+
module Steam
|
4
|
+
module Browser
|
5
|
+
class HtmlUnit
|
6
|
+
class Drb
|
7
|
+
attr_reader :process, :connection, :options
|
8
|
+
|
9
|
+
def initialize(connection, options = {})
|
10
|
+
@connection, @options = connection, options
|
11
|
+
@process = Steam::Process.new
|
12
|
+
|
13
|
+
process.kill if options[:restart] && process.running?
|
14
|
+
options[:daemon] ? daemonize : start unless process.running?
|
15
|
+
end
|
16
|
+
|
17
|
+
def object
|
18
|
+
@object ||= DRbObject.new(nil, Steam.config[:drb_uri])
|
19
|
+
end
|
20
|
+
|
21
|
+
def daemonize
|
22
|
+
options[:keep_alive] = true unless options.key?(:keep_alive)
|
23
|
+
process.fork(options) { start }
|
24
|
+
sleep(1) # FIXME
|
25
|
+
end
|
26
|
+
|
27
|
+
def start
|
28
|
+
uri = Steam.config[:drb_uri]
|
29
|
+
DRb.start_service(uri, HtmlUnit.new(connection, options))
|
30
|
+
puts "HtmlUnit ready and listening at #{uri} [#{::Process.pid}]"
|
31
|
+
DRb.thread.join
|
32
|
+
end
|
33
|
+
|
34
|
+
def restart
|
35
|
+
process.kill if process.running?
|
36
|
+
daemonize
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method, *args, &block)
|
40
|
+
object.send(method, *args, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# module Steam
|
2
|
+
# module HtmlUnit
|
3
|
+
# module Matchers
|
4
|
+
# class HasContent #:nodoc:
|
5
|
+
# def initialize(content)
|
6
|
+
# @content = content
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# def matches?(target)
|
10
|
+
# @target = target
|
11
|
+
# !!@target.locate_element(@content)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def failure_message
|
15
|
+
# "expected the following element's content to #{content_message}:\n#{squeeze_space(@target.page.body)}"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def negative_failure_message
|
19
|
+
# "expected the following element's content to not #{content_message}:\n#{squeeze_space(@target.page.body)}"
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def squeeze_space(inner_text)
|
23
|
+
# (inner_text || '').gsub(/^\s*$/, "").squeeze("\n")
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def content_message
|
27
|
+
# case @content
|
28
|
+
# when String
|
29
|
+
# "include \"#{@content}\""
|
30
|
+
# when Regexp
|
31
|
+
# "match #{@content.inspect}"
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # Matches the contents of an HTML document with
|
37
|
+
# # whatever string is supplied
|
38
|
+
# def contain(content)
|
39
|
+
# HasContent.new(content)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # Asserts that the body of the response contain
|
43
|
+
# # the supplied string or regexp
|
44
|
+
# def assert_contain(content)
|
45
|
+
# hc = HasContent.new(content)
|
46
|
+
# assert hc.matches?(response.body), hc.failure_message
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# # Asserts that the body of the response
|
50
|
+
# # does not contain the supplied string or regepx
|
51
|
+
# def assert_not_contain(content)
|
52
|
+
# hc = HasContent.new(content)
|
53
|
+
# assert !hc.matches?(response.body), hc.negative_failure_message
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Wraps a dom.gargoylesoftware.htmlunit.html.HtmlPage (which is returned by
|
2
|
+
# most browser actions such as click, drag, drop etc.) with a nicer interface.
|
3
|
+
|
4
|
+
module Steam
|
5
|
+
module Browser
|
6
|
+
class HtmlUnit
|
7
|
+
class Page
|
8
|
+
attr_reader
|
9
|
+
|
10
|
+
def initialize(page)
|
11
|
+
@page = page
|
12
|
+
end
|
13
|
+
|
14
|
+
def url
|
15
|
+
@page.getWebResponse.getRequestSettings.getUrl.toString
|
16
|
+
end
|
17
|
+
|
18
|
+
def status
|
19
|
+
@page.getWebResponse.getStatusCode
|
20
|
+
end
|
21
|
+
|
22
|
+
def headers
|
23
|
+
@page.getWebResponse.getResponseHeaders.toArray.inject({}) do |headers, pair|
|
24
|
+
headers[pair.name] = pair.value
|
25
|
+
headers
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def body
|
30
|
+
@page.asXml
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute(javascript)
|
34
|
+
@page.executeJavaScript(javascript)
|
35
|
+
end
|
36
|
+
|
37
|
+
def sourceCode
|
38
|
+
@page.asXml
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_a
|
42
|
+
[body, status, headers]
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method, *args)
|
46
|
+
return @page.send(method, *args)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# Mimicks the com.gargoylesoftware.htmlunit.WebRequestSettings api so it can be
|
2
|
+
# returned by an object that mimicks com.gargoylesoftware.htmlunit.WebConnection
|
3
|
+
# Not currently used in Steam, but useful for experimental stuff.
|
4
|
+
|
5
|
+
module Steam
|
6
|
+
module Browser
|
7
|
+
class HtmlUnit
|
8
|
+
class WebResponse
|
9
|
+
Java.import 'java.net.Url'
|
10
|
+
Java.import 'java.io.ByteArrayInputStream'
|
11
|
+
Java.import 'com.gargoylesoftware.htmlunit.WebRequestSettings'
|
12
|
+
|
13
|
+
include Java::Com::Gargoylesoftware::Htmlunit
|
14
|
+
|
15
|
+
classifier = Version.getProductVersion == '2.6' ?
|
16
|
+
'org.apache.commons.httpclient.NameValuePair' : # HtmlUnit 2.6
|
17
|
+
'com.gargoylesoftware.htmlunit.util.NameValuePair' # HtmlUnit 2.7
|
18
|
+
NameValuePair = Java.import(classifier, :NameValuePair)
|
19
|
+
|
20
|
+
attr_reader :request, :response
|
21
|
+
|
22
|
+
def initialize(request, response)
|
23
|
+
@request = request
|
24
|
+
@response = response
|
25
|
+
rescue Exception => e
|
26
|
+
puts e.message
|
27
|
+
e.backtrace.each { |line| puts line }
|
28
|
+
end
|
29
|
+
|
30
|
+
def getRequestSettings
|
31
|
+
@request_settings ||= WebRequestSettings.new(Java::Net::URL.new(request.url))
|
32
|
+
rescue Exception => e
|
33
|
+
puts e.message
|
34
|
+
e.backtrace.each { |line| puts line }
|
35
|
+
end
|
36
|
+
|
37
|
+
def getResponseHeaders
|
38
|
+
@headers ||= begin
|
39
|
+
headers = response.header.map { |key, value| NameValuePair.new(key, value) }
|
40
|
+
Java::Util::Arrays.asList(headers)
|
41
|
+
end
|
42
|
+
rescue Exception => e
|
43
|
+
puts e.message
|
44
|
+
e.backtrace.each { |line| puts line }
|
45
|
+
end
|
46
|
+
|
47
|
+
def getResponseHeaderValue(name)
|
48
|
+
response.header[name]
|
49
|
+
rescue Exception => e
|
50
|
+
puts e.message
|
51
|
+
e.backtrace.each { |line| puts line }
|
52
|
+
end
|
53
|
+
|
54
|
+
def getStatusCode
|
55
|
+
@status ||= response.status
|
56
|
+
rescue Exception => e
|
57
|
+
puts e.message
|
58
|
+
e.backtrace.each { |line| puts line }
|
59
|
+
end
|
60
|
+
|
61
|
+
def getStatusMessage
|
62
|
+
@message ||= Rack::Utils::HTTP_STATUS_CODES[getStatusCode.to_i]
|
63
|
+
rescue Exception => e
|
64
|
+
puts e.message
|
65
|
+
e.backtrace.each { |line| puts line }
|
66
|
+
end
|
67
|
+
|
68
|
+
def getContentType
|
69
|
+
@content_type ||= begin
|
70
|
+
content_type = response.content_type.split(';').first
|
71
|
+
content_type = 'application/x-javascript' if content_type == 'application/javascript'
|
72
|
+
content_type
|
73
|
+
end
|
74
|
+
rescue Exception => e
|
75
|
+
puts e.message
|
76
|
+
e.backtrace.each { |line| puts line }
|
77
|
+
end
|
78
|
+
|
79
|
+
def getContentCharset
|
80
|
+
@content_charset ||= Steam.config[:charset]
|
81
|
+
rescue Exception => e
|
82
|
+
puts e.message
|
83
|
+
e.backtrace.each { |line| puts line }
|
84
|
+
end
|
85
|
+
|
86
|
+
def getContentCharsetOrNull
|
87
|
+
@content_charset_or_null ||= Steam.config[:charset]
|
88
|
+
rescue Exception => e
|
89
|
+
puts e.message
|
90
|
+
e.backtrace.each { |line| puts line }
|
91
|
+
end
|
92
|
+
|
93
|
+
def getContentAsString
|
94
|
+
@content_as_string ||= response.body.join
|
95
|
+
rescue Exception => e
|
96
|
+
puts e.message
|
97
|
+
e.backtrace.each { |line| puts line }
|
98
|
+
end
|
99
|
+
|
100
|
+
def getContentAsStream
|
101
|
+
@content_as_stream ||= begin
|
102
|
+
bytes = getContentAsString.unpack('C*')
|
103
|
+
Java::Io::ByteArrayInputStream.new_with_sig('[B', bytes)
|
104
|
+
end
|
105
|
+
rescue Exception => e
|
106
|
+
puts e.message
|
107
|
+
e.backtrace.each { |line| puts line }
|
108
|
+
end
|
109
|
+
|
110
|
+
def method_missing(method, *args)
|
111
|
+
puts "Method missing in WebResponse: #{method} #{args.map{ |a| a.inspect }.join(', ')}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Steam
|
2
|
+
module Connection
|
3
|
+
autoload :Mock, 'steam/connection/mock'
|
4
|
+
autoload :NetHttp, 'steam/connection/net_http'
|
5
|
+
autoload :OpenUri, 'steam/connection/open_uri'
|
6
|
+
autoload :Rails, 'steam/connection/rails'
|
7
|
+
autoload :Static, 'steam/connection/static'
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Steam
|
4
|
+
module Connection
|
5
|
+
class Mock
|
6
|
+
class << self
|
7
|
+
def default_content_types
|
8
|
+
{
|
9
|
+
:html => 'text/html',
|
10
|
+
:xml => 'application/xml',
|
11
|
+
:javascript => 'application/javascript',
|
12
|
+
:stylesheet => 'text/css'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@responses = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
request = Rack::Request.new(env)
|
23
|
+
response = response(request.request_method, request.url)
|
24
|
+
response = response.call if response.is_a?(Proc)
|
25
|
+
response.to_a
|
26
|
+
end
|
27
|
+
|
28
|
+
def response(method, url)
|
29
|
+
responses(method)[CGI::unescape(url)] || Rack::Response.new('', 404)
|
30
|
+
end
|
31
|
+
|
32
|
+
def mock(*args)
|
33
|
+
headers = args.last.is_a?(Hash) ? args.pop : {}
|
34
|
+
response, url, method = *args.reverse
|
35
|
+
|
36
|
+
responses(method || :get)[url] = case response
|
37
|
+
when Array
|
38
|
+
Rack::Response.new(*response)
|
39
|
+
when String
|
40
|
+
Rack::Response.new(response, 200, headers)
|
41
|
+
else
|
42
|
+
response
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def responses(method)
|
49
|
+
@responses[method.to_s.upcase] ||= {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def content_type(type)
|
53
|
+
self.class.default_content_types[type]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|