http_monkey 0.0.1
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/.gitignore +18 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/Rakefile +19 -0
- data/Readme.md +173 -0
- data/http_monkey.gemspec +27 -0
- data/lib/http_monkey/client/environment.rb +30 -0
- data/lib/http_monkey/client/environment_builder.rb +70 -0
- data/lib/http_monkey/client/http_request.rb +20 -0
- data/lib/http_monkey/client.rb +43 -0
- data/lib/http_monkey/configuration/behaviours.rb +49 -0
- data/lib/http_monkey/configuration/middlewares.rb +29 -0
- data/lib/http_monkey/configuration.rb +36 -0
- data/lib/http_monkey/entry_point.rb +88 -0
- data/lib/http_monkey/middlewares/default_headers.rb +26 -0
- data/lib/http_monkey/middlewares.rb +5 -0
- data/lib/http_monkey/version.rb +3 -0
- data/lib/http_monkey.rb +64 -0
- data/test/http_monkey/client/environment_test.rb +28 -0
- data/test/http_monkey/client_test.rb +28 -0
- data/test/http_monkey/configuration/behaviours_test.rb +34 -0
- data/test/http_monkey/configuration/middlewares_test.rb +73 -0
- data/test/http_monkey/configuration_test.rb +64 -0
- data/test/http_monkey/entry_point_test.rb +135 -0
- data/test/http_monkey/http_monkey_test.rb +26 -0
- data/test/http_monkey/middlewares/default_headers_test.rb +32 -0
- data/test/integration/server.rb +73 -0
- data/test/integration/verbs_test.rb +58 -0
- data/test/test_helper.rb +9 -0
- metadata +191 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Roger Leite http://1up4dev.org
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
ENV["RUBYOPT"] = "rubygems" if ENV["RUBYOPT"].nil?
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.test_files = FileList['test/http_monkey/*_test.rb']
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::TestTask.new("test:integration") do |t|
|
12
|
+
t.libs << "test"
|
13
|
+
t.pattern = "test/integration/*_test.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "For Travis CI with love"
|
17
|
+
task :ci => [:test, :"test:integration"]
|
18
|
+
|
19
|
+
task :default => :ci
|
data/Readme.md
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# HTTP Monkey [](https://travis-ci.org/rogerleite/http_monkey)
|
2
|
+
|
3
|
+
A fluent interface to do HTTP calls, free of fat dependencies and at same time, powered by middlewares rack.
|
4
|
+
|
5
|
+
It's an awesome client with an awful name.
|
6
|
+
|
7
|
+
## Light and powerful
|
8
|
+
|
9
|
+
``` ruby
|
10
|
+
# Works with Entry Point concept
|
11
|
+
response = HttpMonkey.at("http://google.com").get
|
12
|
+
response = HttpMonkey.at("http://google.com").post(:q => "Http Monkey!")
|
13
|
+
puts response.body # More info about response at http://httpirb.com/#responses
|
14
|
+
|
15
|
+
## Headers
|
16
|
+
HttpMonket.at("http://google.com").
|
17
|
+
with_header("Content-Type" => "text/html").
|
18
|
+
with_header("X-Custom" => "sample").
|
19
|
+
get
|
20
|
+
|
21
|
+
## Cookies
|
22
|
+
HttpMonkey.at("http://google.com").set_cookie("blah").get
|
23
|
+
|
24
|
+
## Basic Authentication
|
25
|
+
HttpMonkey.at("http://user:pass@google.com").get
|
26
|
+
HttpMonkey.at("http://google.com").
|
27
|
+
basic_auth("user", "pass").
|
28
|
+
get
|
29
|
+
|
30
|
+
## Request Internals (yields HTTPI::Request, to set your obscure desires)
|
31
|
+
HttpMonkey.at("http://google.com").yield_request do |req|
|
32
|
+
req.proxy = "http://proxy.com"
|
33
|
+
req.open_timeout = 30
|
34
|
+
req.read_timeout = 15
|
35
|
+
end.get
|
36
|
+
|
37
|
+
# SSL
|
38
|
+
HttpMonkey.at("http://google.com").yield_request do |req|
|
39
|
+
req.auth.ssl.cert_key_file = "client_key.pem" # the private key file to use
|
40
|
+
req.auth.ssl.cert_key_password = "C3rtP@ssw0rd" # the key file's password
|
41
|
+
req.auth.ssl.cert_file = "client_cert.pem" # the certificate file to use
|
42
|
+
req.auth.ssl.ca_cert_file = "ca_cert.pem" # the ca certificate file to use
|
43
|
+
req.auth.ssl.verify_mode = :none # or one of [:peer, :fail_if_no_peer_cert, :client_once]
|
44
|
+
req.auth.ssl.ssl_version = :TLSv1 # or one of [:SSLv2, :SSLv3]
|
45
|
+
end.get
|
46
|
+
|
47
|
+
# Default HTTP Headers (to all requests)
|
48
|
+
HttpMonkey.configure do
|
49
|
+
middlewares.use HttpMonkey::Middlewares::DefaultHeaders, {"Content-Type" => "application/json"}
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## Flexibility
|
54
|
+
|
55
|
+
You can configure the default or build your own client and define how it should behave.
|
56
|
+
|
57
|
+
You can also define net adapter, behaviours and middlewares by request.
|
58
|
+
|
59
|
+
``` ruby
|
60
|
+
# Changing default client
|
61
|
+
HttpMonkey.configure do
|
62
|
+
net_adapter :curb
|
63
|
+
behaviours.on(500) do |client, request, response|
|
64
|
+
raise "Server side error :X"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Works with status code callbacks (here known as behaviours)
|
69
|
+
chimp = HttpMonkey.build do
|
70
|
+
behaviours do
|
71
|
+
# 2xx range
|
72
|
+
on(200..299) do |client, request, response|
|
73
|
+
response
|
74
|
+
end
|
75
|
+
# Redirects
|
76
|
+
on([301, 302]) do |client, request, response|
|
77
|
+
raise "Redirect error"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
chimp.at("http://google.com").get # raises Redirect error
|
83
|
+
|
84
|
+
# by request
|
85
|
+
chimp.at("http://google.com").get do
|
86
|
+
behaviours.on(200) do |client, request, response|
|
87
|
+
raise "ok" # only for this request
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
## Choose your HTTP client
|
93
|
+
|
94
|
+
Thanks to [HTTPI](http://httpirb.com/), you can choose different HTTP clients:
|
95
|
+
|
96
|
+
* [HTTPClient](http://rubygems.org/gems/httpclient)
|
97
|
+
* [Curb](http://rubygems.org/gems/curb)
|
98
|
+
* [Net::HTTP](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc)
|
99
|
+
|
100
|
+
*Important*: If you want to use anything other than Net::HTTP, you need to manually require the library or make sure it’s available in your load path.
|
101
|
+
|
102
|
+
``` ruby
|
103
|
+
# When you build your own client, you can define which Http client to use.
|
104
|
+
chimp = HttpMonkey.build do
|
105
|
+
# HTTP clients available [:httpclient, :curb, :net_http]
|
106
|
+
net_adapter :curb # default :net_http
|
107
|
+
# [...]
|
108
|
+
end
|
109
|
+
|
110
|
+
# You can also change you net_adapter by request
|
111
|
+
chimp.at("http://google.com").get do
|
112
|
+
# only on this request, use :httpclient
|
113
|
+
net_adapter :httpclient
|
114
|
+
# [...]
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
## More power to the people (for God sake!)
|
119
|
+
|
120
|
+
Easy to extend, using the power of Rack middleware interface.
|
121
|
+
|
122
|
+
``` ruby
|
123
|
+
|
124
|
+
class Logger
|
125
|
+
def initialize(app)
|
126
|
+
@app = app
|
127
|
+
end
|
128
|
+
def call(env)
|
129
|
+
puts "-> before #{env.inspect} #{Time.now.inspect}"
|
130
|
+
result = @app.call(env)
|
131
|
+
puts "-> after #{env.inspect} #{Time.now.inspect}"
|
132
|
+
result
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Add custom middlewares to default stack
|
137
|
+
HttpMonkey.configure do
|
138
|
+
middlewares do
|
139
|
+
use Logger
|
140
|
+
end
|
141
|
+
end
|
142
|
+
# Now all requests uses Logger
|
143
|
+
response = HttpMonkey.at("http://google.com").get
|
144
|
+
|
145
|
+
# or when you build your own client
|
146
|
+
chimp = HttpMonkey.build do
|
147
|
+
middlewares do
|
148
|
+
use Logger
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# or by request
|
153
|
+
chimp.at("http://google.com").get do
|
154
|
+
middlewares.use Logger
|
155
|
+
# [...]
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
Some ideas:
|
160
|
+
|
161
|
+
* Cache? [rack-cache](https://github.com/rtomayko/rack-cache)
|
162
|
+
* Logger? [http://rack.rubyforge.org/doc/Rack/Logger.html]
|
163
|
+
* Profile?
|
164
|
+
* Support to specific Media Type?
|
165
|
+
|
166
|
+
## Easy to contribute
|
167
|
+
|
168
|
+
Suggestions, bugs and pull requests, here at [github.com/rogerleite/http_monkey](http://github.com/rogerleite/http_monkey).
|
169
|
+
`bundle install`, `rake test` and be happy!
|
170
|
+
|
171
|
+
## License
|
172
|
+
|
173
|
+
HTTP Monkey is copyright 2012 Roger Leite and contributors. It is licensed under the MIT license. See the include LICENSE file for details.
|
data/http_monkey.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'http_monkey/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "http_monkey"
|
8
|
+
gem.version = HttpMonkey::VERSION
|
9
|
+
gem.authors = ["Roger Leite"]
|
10
|
+
gem.email = ["roger.barreto@gmail.com"]
|
11
|
+
gem.description = %q{A fluent interface to do HTTP calls, free of fat dependencies and at same time, powered by middlewares rack.}
|
12
|
+
gem.summary = %q{A fluent interface to do HTTP calls, free of fat dependencies and at same time, powered by middlewares rack.}
|
13
|
+
gem.homepage = "https://github.com/rogerleite/http_monkey"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency "rack"
|
21
|
+
gem.add_runtime_dependency "httpi", "~> 1.1"
|
22
|
+
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
gem.add_development_dependency "minitest", "~> 3"
|
25
|
+
gem.add_development_dependency "minitest-reporters", "~> 0.7.0"
|
26
|
+
gem.add_development_dependency "mocha"
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
# Rack environment with helpers.
|
4
|
+
class Client::Environment
|
5
|
+
|
6
|
+
def initialize(env)
|
7
|
+
@env = env
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
@env[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(key, value)
|
15
|
+
@env[key] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
# From {"HTTP_CONTENT_TYPE" => "text/html"} to {"Content-Type" => "text/html"}
|
19
|
+
def http_headers
|
20
|
+
req_headers = @env.reject {|k,v| !k.start_with? "HTTP_" }
|
21
|
+
normalized = req_headers.map do |key, value|
|
22
|
+
new_key = key.sub("HTTP_",'').split('_').map(&:capitalize).join('-')
|
23
|
+
[new_key, value]
|
24
|
+
end
|
25
|
+
Hash[normalized]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
# Great inspiration from https://github.com/rack/rack/blob/master/lib/rack/mock.rb,
|
4
|
+
# specially from Rack::MockRequest
|
5
|
+
class Client::EnvironmentBuilder
|
6
|
+
|
7
|
+
DEFAULT_ENV = {
|
8
|
+
"rack.version" => Rack::VERSION,
|
9
|
+
"rack.input" => nil,
|
10
|
+
"rack.errors" => STDERR,
|
11
|
+
"rack.multithread" => true,
|
12
|
+
"rack.multiprocess" => false,
|
13
|
+
"rack.run_once" => false,
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize(client, method, request)
|
17
|
+
@client = client
|
18
|
+
@method = method
|
19
|
+
@request = request
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_env
|
23
|
+
uri = @request.url
|
24
|
+
rack_input = normalize_body(@request.body)
|
25
|
+
|
26
|
+
env = DEFAULT_ENV.dup
|
27
|
+
env = env.merge({
|
28
|
+
# request info
|
29
|
+
'REQUEST_METHOD' => @method.to_s.upcase,
|
30
|
+
'SERVER_NAME' => uri.host,
|
31
|
+
'SERVER_PORT' => (uri.port || uri.inferred_port).to_s,
|
32
|
+
'QUERY_STRING' => uri.query || "",
|
33
|
+
'PATH_INFO' => (!uri.path || uri.path.empty?) ? "/" : uri.path,
|
34
|
+
'rack.url_scheme' => uri.scheme,
|
35
|
+
'HTTPS' => (uri.scheme == "https" ? "on" : "off"),
|
36
|
+
'SCRIPT_NAME' => "", # call me Suzy
|
37
|
+
|
38
|
+
'REQUEST_URI' => uri.request_uri,
|
39
|
+
'HTTP_HOST' => uri.host,
|
40
|
+
'rack.input' => rack_input,
|
41
|
+
'CONTENT_LENGTH' => rack_input.length.to_s,
|
42
|
+
|
43
|
+
# custom info
|
44
|
+
'http_monkey.request' => [@method, @request, @client.net_adapter]
|
45
|
+
}).update(http_headers)
|
46
|
+
env
|
47
|
+
end
|
48
|
+
|
49
|
+
# From {"Content-Type" => "text/html"} to {"HTTP_CONTENT_TYPE" => "text/html"}
|
50
|
+
def http_headers
|
51
|
+
env_headers = @request.headers.map do |key, value|
|
52
|
+
["HTTP_#{key.to_s.upcase.gsub("-", "_")}", value]
|
53
|
+
end
|
54
|
+
Hash[env_headers]
|
55
|
+
end
|
56
|
+
|
57
|
+
def normalize_body(body)
|
58
|
+
return "" if body.nil?
|
59
|
+
input = body.dup
|
60
|
+
input.force_encoding("ASCII-8BIT") if input.respond_to?(:force_encoding)
|
61
|
+
# TODO: search about setting encoding binary
|
62
|
+
#input = StringIO.new(input) if input.is_a?(String)
|
63
|
+
#input.set_encoding(Encoding::BINARY) if input.respond_to?(:set_encoding)
|
64
|
+
#input = input.string if input.respond_to?(:string)
|
65
|
+
input
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
# Main App middleware
|
4
|
+
# Responsible to make HTTP request
|
5
|
+
class Client::HttpRequest
|
6
|
+
|
7
|
+
def self.call(env)
|
8
|
+
env = Client::Environment.new(env)
|
9
|
+
method, request, net_adapter = env['http_monkey.request']
|
10
|
+
|
11
|
+
request.headers = env.http_headers
|
12
|
+
request.body = env['rack.input']
|
13
|
+
|
14
|
+
response = HTTPI.request(method, request, net_adapter)
|
15
|
+
[response.code, response.headers, response.body]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@conf = Configuration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize_copy(source)
|
10
|
+
super
|
11
|
+
@conf = @conf.clone
|
12
|
+
end
|
13
|
+
|
14
|
+
def at(url)
|
15
|
+
HttpMonkey::EntryPoint.new(self, url)
|
16
|
+
end
|
17
|
+
|
18
|
+
def net_adapter
|
19
|
+
@conf.net_adapter
|
20
|
+
end
|
21
|
+
|
22
|
+
def configure(&block)
|
23
|
+
@conf.instance_eval(&block) if block_given?
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def http_request(method, request)
|
28
|
+
env = Client::EnvironmentBuilder.new(self, method, request).to_env
|
29
|
+
code, headers, body = @conf.middlewares.execute(Client::HttpRequest, env)
|
30
|
+
body.close if body.respond_to?(:close) # close when is a Rack::BodyProxy
|
31
|
+
response = HTTPI::Response.new(code, headers, body)
|
32
|
+
|
33
|
+
if (behaviour = @conf.behaviours.find(response.code))
|
34
|
+
behaviour.call(self, request, response)
|
35
|
+
else
|
36
|
+
unknown_behaviour = @conf.behaviours.unknown_behaviour
|
37
|
+
unknown_behaviour.call(self, request, response) if unknown_behaviour.respond_to?(:call)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
class Configuration::Behaviours
|
4
|
+
|
5
|
+
attr_reader :unknown_behaviour
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.clear!
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize_copy(source)
|
12
|
+
super
|
13
|
+
@behaviours = @behaviours.clone
|
14
|
+
@behaviours_range = @behaviours_range.clone
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear!
|
18
|
+
@behaviours = {}
|
19
|
+
@behaviours_range = {}
|
20
|
+
@unknown_behaviour = nil
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def on(code, &block)
|
25
|
+
if code.is_a?(Integer)
|
26
|
+
@behaviours[code] = block
|
27
|
+
elsif code.respond_to?(:include?)
|
28
|
+
@behaviours_range[code] = block
|
29
|
+
end
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_unknown(&block)
|
34
|
+
@unknown_behaviour = block
|
35
|
+
end
|
36
|
+
|
37
|
+
def find(code)
|
38
|
+
behaviour = @behaviours[code]
|
39
|
+
if behaviour.nil?
|
40
|
+
_, behaviour = @behaviours_range.detect do |range, proc|
|
41
|
+
range.include?(code)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
behaviour
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
# Heavily inspired on Rack::Builder (http://rack.rubyforge.org/doc/Rack/Builder.html)
|
4
|
+
class Configuration::Middlewares
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@chain = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize_copy(source)
|
11
|
+
super
|
12
|
+
@chain = @chain.clone
|
13
|
+
end
|
14
|
+
|
15
|
+
def use(middleware, *args, &block)
|
16
|
+
@chain << lambda { |app| middleware.new(app, *args, &block) }
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute(app, env)
|
21
|
+
stacked_middleware = @chain.reverse.inject(app) do |app, middle|
|
22
|
+
middle.call(app)
|
23
|
+
end
|
24
|
+
stacked_middleware.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module HttpMonkey
|
2
|
+
|
3
|
+
class Configuration
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
net_adapter(:net_http) #default adapter
|
7
|
+
@behaviours = HttpMonkey::Configuration::Behaviours.new
|
8
|
+
# behaviour default always return response
|
9
|
+
@behaviours.on_unknown { |client, req, response| response }
|
10
|
+
@middlewares = HttpMonkey::Configuration::Middlewares.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize_copy(source)
|
14
|
+
super
|
15
|
+
@behaviours = @behaviours.clone
|
16
|
+
@middlewares = @middlewares.clone
|
17
|
+
end
|
18
|
+
|
19
|
+
def net_adapter(adapter = nil)
|
20
|
+
@net_adapter = adapter unless adapter.nil?
|
21
|
+
@net_adapter
|
22
|
+
end
|
23
|
+
|
24
|
+
def behaviours(&block)
|
25
|
+
@behaviours.instance_eval(&block) if block_given?
|
26
|
+
@behaviours
|
27
|
+
end
|
28
|
+
|
29
|
+
def middlewares(&block)
|
30
|
+
@middlewares.instance_eval(&block) if block_given?
|
31
|
+
@middlewares
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module HttpMonkey
|
4
|
+
|
5
|
+
module EntryPointFluentInterface
|
6
|
+
|
7
|
+
def with_header(header)
|
8
|
+
@request.headers.update(header)
|
9
|
+
self
|
10
|
+
end
|
11
|
+
alias :with_headers :with_header
|
12
|
+
|
13
|
+
def set_cookie(cookie)
|
14
|
+
@request.headers["Cookie"] = cookie if cookie
|
15
|
+
self
|
16
|
+
end
|
17
|
+
alias :set_cookies :set_cookie
|
18
|
+
|
19
|
+
def basic_auth(user, pass)
|
20
|
+
@request.auth.basic(user, pass)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def digest_auth(user, pass)
|
25
|
+
@request.auth.digest(user, pass)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
# Yields internal HTTPI::Request
|
30
|
+
def yield_request
|
31
|
+
yield(@request) if block_given?
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class EntryPoint
|
38
|
+
|
39
|
+
def initialize(client, url)
|
40
|
+
@client = client
|
41
|
+
@request = HTTPI::Request.new(url)
|
42
|
+
end
|
43
|
+
|
44
|
+
def _request
|
45
|
+
@request
|
46
|
+
end
|
47
|
+
|
48
|
+
include EntryPointFluentInterface
|
49
|
+
|
50
|
+
def get(query_param = nil, &block)
|
51
|
+
# pending pull request to httpi support @request.query=
|
52
|
+
if query_param.kind_of?(Hash)
|
53
|
+
query_param = Rack::Utils.build_query(query_param)
|
54
|
+
end
|
55
|
+
query_param = query_param.to_s unless query_param.is_a?(String)
|
56
|
+
@request.url.query = query_param unless query_param.empty?
|
57
|
+
|
58
|
+
capture_client(&block).http_request(:get, @request)
|
59
|
+
end
|
60
|
+
|
61
|
+
def post(body_param, &block)
|
62
|
+
@request.body = body_param
|
63
|
+
capture_client(&block).http_request(:post, @request)
|
64
|
+
end
|
65
|
+
|
66
|
+
def put(body_param, &block)
|
67
|
+
@request.body = body_param
|
68
|
+
capture_client(&block).http_request(:put, @request)
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(&block)
|
72
|
+
capture_client(&block).http_request(:delete, @request)
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
# If block given, clones actual client and uses
|
78
|
+
# the block as configuration
|
79
|
+
def capture_client(&block)
|
80
|
+
if block_given?
|
81
|
+
@client.clone.configure(&block)
|
82
|
+
else
|
83
|
+
@client
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module HttpMonkey::Middlewares
|
2
|
+
|
3
|
+
# Allow to set default HTTP headers to all requests
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# use HttpMonkey::Middlewares::DefaultHeaders, {"Content-Type" => "text/html",
|
8
|
+
# "X-Custom" => "custom"}
|
9
|
+
class DefaultHeaders
|
10
|
+
|
11
|
+
def initialize(app, headers = {})
|
12
|
+
@app = app
|
13
|
+
@headers = headers
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@headers.each do |header, value|
|
18
|
+
http_header = "HTTP_#{header.to_s.upcase.gsub("-", "_")}"
|
19
|
+
env[http_header] = value unless env.key?(http_header)
|
20
|
+
end
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|