patron 0.4.20 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +27 -13
- data/README.md +17 -0
- data/Rakefile +1 -8
- data/ext/patron/extconf.rb +3 -1
- data/ext/patron/session_ext.c +17 -5
- data/lib/patron/request.rb +3 -3
- data/lib/patron/response.rb +15 -13
- data/lib/patron/session.rb +23 -7
- data/lib/patron/version.rb +1 -1
- data/patron.gemspec +1 -1
- data/spec/patron_spec.rb +2 -2
- data/spec/request_spec.rb +11 -11
- data/spec/response_spec.rb +6 -6
- data/spec/session_spec.rb +138 -60
- data/spec/session_ssl_spec.rb +52 -53
- data/spec/spec_helper.rb +10 -0
- data/spec/util_spec.rb +20 -20
- metadata +21 -31
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d00ecf42f426d8d52b56cd005e3c0d1740819f96
|
4
|
+
data.tar.gz: b4635d6adc592ac3576495fa04578f1256b8517f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 37193992f549400596a21c553023befd7e5c47b360eaf7a8ac1de2347544e2adce5e462b76543cb98ade09af6b8656426176262d25bc46e12d22db128b1ded3a
|
7
|
+
data.tar.gz: 9be5c558dd549b671137e5f62e29a9f3af2a63f35b1e7525d5afe1450a9a689973fd5f221e92de39d9bed7c9319be13bfbfa73b87de8bda4fb31284952d888fd
|
data/Gemfile.lock
CHANGED
@@ -6,19 +6,30 @@ PATH
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
10
|
-
|
11
|
-
|
9
|
+
diff-lcs (1.2.5)
|
10
|
+
docile (1.1.5)
|
11
|
+
json (1.8.3)
|
12
|
+
rake (10.4.2)
|
13
|
+
rake-compiler (0.9.5)
|
12
14
|
rake
|
13
|
-
|
14
|
-
|
15
|
-
rspec-
|
16
|
-
rspec-
|
17
|
-
|
18
|
-
|
19
|
-
rspec-expectations (
|
20
|
-
diff-lcs (
|
21
|
-
|
15
|
+
rspec (3.3.0)
|
16
|
+
rspec-core (~> 3.3.0)
|
17
|
+
rspec-expectations (~> 3.3.0)
|
18
|
+
rspec-mocks (~> 3.3.0)
|
19
|
+
rspec-core (3.3.2)
|
20
|
+
rspec-support (~> 3.3.0)
|
21
|
+
rspec-expectations (3.3.1)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.3.0)
|
24
|
+
rspec-mocks (3.3.2)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.3.0)
|
27
|
+
rspec-support (3.3.0)
|
28
|
+
simplecov (0.10.0)
|
29
|
+
docile (~> 1.1.0)
|
30
|
+
json (~> 1.8)
|
31
|
+
simplecov-html (~> 0.10.0)
|
32
|
+
simplecov-html (0.10.0)
|
22
33
|
|
23
34
|
PLATFORMS
|
24
35
|
ruby
|
@@ -27,5 +38,8 @@ DEPENDENCIES
|
|
27
38
|
bundler (>= 1.0.0)
|
28
39
|
patron!
|
29
40
|
rake-compiler (>= 0.7.5)
|
30
|
-
rcov (>= 0.9.9)
|
31
41
|
rspec (>= 2.3.0)
|
42
|
+
simplecov (>= 0.10.0)
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
1.10.6
|
data/README.md
CHANGED
@@ -17,6 +17,23 @@ requests:
|
|
17
17
|
sess.timeout = 10
|
18
18
|
sess.base_url = "http://myserver.com:9900"
|
19
19
|
sess.headers['User-Agent'] = 'myapp/1.0'
|
20
|
+
|
21
|
+
You can set options with a hash in the constructor:
|
22
|
+
|
23
|
+
sess = Patron::Session.new({ :timeout => 10,
|
24
|
+
:base_url => 'http://myserver.com:9900',
|
25
|
+
:headers => {'User-Agent' => 'myapp/1.0'} } )
|
26
|
+
|
27
|
+
Or the set options in a block:
|
28
|
+
|
29
|
+
sess = Patron::Session.new do |patron|
|
30
|
+
patron.timeout = 10
|
31
|
+
patron.base_url = 'http://myserver.com:9900'
|
32
|
+
patron.headers = {'User-Agent' => 'myapp/1.0'}
|
33
|
+
end
|
34
|
+
|
35
|
+
Output debug log:
|
36
|
+
|
20
37
|
sess.enable_debug "/tmp/patron.debug"
|
21
38
|
|
22
39
|
The Session is used to make HTTP requests.
|
data/Rakefile
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
##
|
23
23
|
## -------------------------------------------------------------------
|
24
24
|
require 'rake/clean'
|
25
|
-
require '
|
25
|
+
require 'rdoc/task'
|
26
26
|
require 'rake/extensiontask'
|
27
27
|
require 'rspec/core/rake_task'
|
28
28
|
require 'bundler'
|
@@ -59,11 +59,4 @@ end
|
|
59
59
|
|
60
60
|
task :spec => [:compile]
|
61
61
|
|
62
|
-
desc "Run specs with RCov"
|
63
|
-
RSpec::Core::RakeTask.new('spec:rcov') do |t|
|
64
|
-
t.pattern = 'spec/**/*_spec.rb'
|
65
|
-
t.rcov = true
|
66
|
-
t.rcov_opts = %q(--sort coverage --comments --exclude "spec")
|
67
|
-
end
|
68
|
-
|
69
62
|
task :default => :spec
|
data/ext/patron/extconf.rb
CHANGED
@@ -44,6 +44,8 @@ if CONFIG['CC'] =~ /gcc/
|
|
44
44
|
end
|
45
45
|
|
46
46
|
$defs.push("-DUSE_TBR")
|
47
|
-
$defs.push("-
|
47
|
+
$defs.push("-DHAVE_THREAD_H") if have_header('ruby/thread.h')
|
48
|
+
$defs.push("-DHAVE_TBR") if have_func('rb_thread_blocking_region', 'ruby.h')
|
49
|
+
$defs.push("-DHAVE_TCWOGVL") if have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
48
50
|
|
49
51
|
create_makefile 'patron/session_ext'
|
data/ext/patron/session_ext.c
CHANGED
@@ -23,6 +23,9 @@
|
|
23
23
|
*
|
24
24
|
\* -------------------------------------------------------------------------- */
|
25
25
|
#include <ruby.h>
|
26
|
+
#if defined(USE_TBR) && defined(HAVE_THREAD_H)
|
27
|
+
#include <ruby/thread.h>
|
28
|
+
#endif
|
26
29
|
#include <curl/curl.h>
|
27
30
|
#include "membuffer.h"
|
28
31
|
#include "sglib.h" /* Simple Generic Library -> http://sglib.sourceforge.net */
|
@@ -109,7 +112,7 @@ struct curl_state_list {
|
|
109
112
|
struct curl_state_list *next;
|
110
113
|
};
|
111
114
|
|
112
|
-
#define CS_LIST_COMPARATOR(p, _state_) (p->state
|
115
|
+
#define CS_LIST_COMPARATOR(p, _state_) (p->state - _state_)
|
113
116
|
|
114
117
|
static struct curl_state_list *cs_list = NULL;
|
115
118
|
|
@@ -128,9 +131,9 @@ static void cs_list_remove(struct curl_state *state) {
|
|
128
131
|
struct curl_state_list *item = NULL;
|
129
132
|
|
130
133
|
assert(state != NULL);
|
131
|
-
|
134
|
+
|
135
|
+
SGLIB_LIST_DELETE_IF_MEMBER(struct curl_state_list, cs_list, state, CS_LIST_COMPARATOR, next, item);
|
132
136
|
if (item) {
|
133
|
-
SGLIB_LIST_DELETE(struct curl_state_list, cs_list, item, next);
|
134
137
|
ruby_xfree(item);
|
135
138
|
}
|
136
139
|
}
|
@@ -355,7 +358,9 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
355
358
|
}
|
356
359
|
|
357
360
|
action = SYM2ID(action_name);
|
358
|
-
|
361
|
+
if(rb_iv_get(request, "@force_ipv4")) {
|
362
|
+
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
363
|
+
}
|
359
364
|
if (action == rb_intern("get")) {
|
360
365
|
VALUE data = rb_iv_get(request, "@upload_data");
|
361
366
|
VALUE download_file = rb_iv_get(request, "@file_name");
|
@@ -593,11 +598,18 @@ static VALUE perform_request(VALUE self) {
|
|
593
598
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
|
594
599
|
}
|
595
600
|
|
596
|
-
#if defined(HAVE_TBR) && defined(USE_TBR)
|
601
|
+
#if (defined(HAVE_TBR) || defined(HAVE_TCWOGVL)) && defined(USE_TBR)
|
602
|
+
#if defined(HAVE_TCWOGVL)
|
603
|
+
ret = (CURLcode) rb_thread_call_without_gvl(
|
604
|
+
(void *(*)(void *)) curl_easy_perform, curl,
|
605
|
+
RUBY_UBF_IO, 0
|
606
|
+
);
|
607
|
+
#else
|
597
608
|
ret = (CURLcode) rb_thread_blocking_region(
|
598
609
|
(rb_blocking_function_t*) curl_easy_perform, curl,
|
599
610
|
RUBY_UBF_IO, 0
|
600
611
|
);
|
612
|
+
#endif
|
601
613
|
#else
|
602
614
|
ret = curl_easy_perform(curl);
|
603
615
|
#endif
|
data/lib/patron/request.rb
CHANGED
@@ -46,12 +46,12 @@ module Patron
|
|
46
46
|
:url, :username, :password, :file_name, :proxy, :proxy_type, :insecure,
|
47
47
|
:ignore_content_length, :multipart, :action, :timeout, :connect_timeout,
|
48
48
|
:max_redirects, :headers, :auth_type, :upload_data, :buffer_size, :cacert,
|
49
|
-
:ssl_version
|
49
|
+
:ssl_version, :force_ipv4
|
50
50
|
]
|
51
51
|
|
52
52
|
WRITER_VARS = [
|
53
53
|
:url, :username, :password, :file_name, :proxy, :proxy_type, :insecure,
|
54
|
-
:ignore_content_length, :multipart, :cacert, :ssl_version
|
54
|
+
:ignore_content_length, :multipart, :cacert, :ssl_version, :force_ipv4
|
55
55
|
]
|
56
56
|
|
57
57
|
attr_reader *READER_VARS
|
@@ -110,7 +110,7 @@ module Patron
|
|
110
110
|
|
111
111
|
@connect_timeout = new_timeout.to_i
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
def max_redirects=(new_max_redirects)
|
115
115
|
if new_max_redirects.to_i < -1
|
116
116
|
raise ArgumentError, "Max redirects must be a positive integer, 0 or -1"
|
data/lib/patron/response.rb
CHANGED
@@ -85,20 +85,22 @@ module Patron
|
|
85
85
|
def parse_headers(header_data)
|
86
86
|
@headers = {}
|
87
87
|
|
88
|
-
header_data.split(
|
89
|
-
|
90
|
-
|
88
|
+
lines = header_data.split("\r\n")
|
89
|
+
|
90
|
+
@status_line = lines.shift
|
91
|
+
|
92
|
+
lines.each do |line|
|
93
|
+
break if line.empty?
|
94
|
+
|
95
|
+
hdr, val = line.split(":", 2)
|
96
|
+
|
97
|
+
val.strip! unless val.nil?
|
98
|
+
|
99
|
+
if @headers.key?(hdr)
|
100
|
+
@headers[hdr] = [@headers[hdr]] unless @headers[hdr].kind_of? Array
|
101
|
+
@headers[hdr] << val
|
91
102
|
else
|
92
|
-
|
93
|
-
unless parts.empty?
|
94
|
-
parts[1].strip! unless parts[1].nil?
|
95
|
-
if @headers.has_key?(parts[0])
|
96
|
-
@headers[parts[0]] = [@headers[parts[0]]] unless @headers[parts[0]].kind_of? Array
|
97
|
-
@headers[parts[0]] << parts[1]
|
98
|
-
else
|
99
|
-
@headers[parts[0]] = parts[1]
|
100
|
-
end
|
101
|
-
end
|
103
|
+
@headers[hdr] = val
|
102
104
|
end
|
103
105
|
end
|
104
106
|
end
|
data/lib/patron/session.rb
CHANGED
@@ -83,16 +83,31 @@ module Patron
|
|
83
83
|
|
84
84
|
# Default encoding of responses. Used if no charset is provided by the host.
|
85
85
|
attr_accessor :default_response_charset
|
86
|
+
|
87
|
+
# Force curl to use IPv4
|
88
|
+
attr_accessor :force_ipv4
|
86
89
|
|
87
90
|
private :handle_request, :enable_cookie_session, :set_debug_file
|
88
91
|
|
89
92
|
# Create a new Session object.
|
90
|
-
def initialize
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
def initialize(args = {}, &block)
|
94
|
+
|
95
|
+
# Allows accessors to be set via constructor hash. Ex: {:base_url => 'www.home.com'}
|
96
|
+
args.each do |attribute, value|
|
97
|
+
send("#{attribute}=", value)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Allows accessors to be set via block.
|
101
|
+
if block_given?
|
102
|
+
yield self
|
103
|
+
end
|
104
|
+
|
105
|
+
@headers ||= {}
|
106
|
+
@timeout ||= 5
|
107
|
+
@connect_timeout ||= 1
|
108
|
+
@max_redirects ||= 5
|
109
|
+
@auth_type ||= :basic
|
110
|
+
@force_ipv4 ||= false
|
96
111
|
end
|
97
112
|
|
98
113
|
# Turn on cookie handling for this session, storing them in memory by
|
@@ -211,6 +226,7 @@ module Patron
|
|
211
226
|
req.headers = self.headers.merge headers
|
212
227
|
req.timeout = options.fetch :timeout, self.timeout
|
213
228
|
req.connect_timeout = options.fetch :connect_timeout, self.connect_timeout
|
229
|
+
req.force_ipv4 = options.fetch :force_ipv4, self.force_ipv4
|
214
230
|
req.max_redirects = options.fetch :max_redirects, self.max_redirects
|
215
231
|
req.username = options.fetch :username, self.username
|
216
232
|
req.password = options.fetch :password, self.password
|
@@ -229,7 +245,7 @@ module Patron
|
|
229
245
|
base_url = self.base_url.to_s
|
230
246
|
url = url.to_s
|
231
247
|
raise ArgumentError, "Empty URL" if base_url.empty? && url.empty?
|
232
|
-
uri = URI.join(base_url, url)
|
248
|
+
uri = URI.parse(base_url.empty? ? url : File.join(base_url, url))
|
233
249
|
query = uri.query.to_s.split('&')
|
234
250
|
query += options[:query].is_a?(Hash) ? Util.build_query_pairs_from_hash(options[:query]) : options[:query].to_s.split('&')
|
235
251
|
uri.query = query.join('&')
|
data/lib/patron/version.rb
CHANGED
data/patron.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
18
|
s.add_development_dependency "rake-compiler", ">= 0.7.5"
|
19
19
|
s.add_development_dependency "rspec", ">= 2.3.0"
|
20
|
-
s.add_development_dependency "
|
20
|
+
s.add_development_dependency "simplecov", ">= 0.10.0"
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
23
23
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
data/spec/patron_spec.rb
CHANGED
@@ -27,12 +27,12 @@ describe Patron do
|
|
27
27
|
|
28
28
|
it "should return the version number of the Patron library" do
|
29
29
|
version = Patron.version
|
30
|
-
version.
|
30
|
+
expect(version).to match(%r|^\d+.\d+.\d+$|)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should return the version number of the libcurl library" do
|
34
34
|
version = Patron.libcurl_version
|
35
|
-
version.
|
35
|
+
expect(version).to match(%r|^libcurl/\d+.\d+.\d+|)
|
36
36
|
end
|
37
37
|
|
38
38
|
end
|
data/spec/request_spec.rb
CHANGED
@@ -34,12 +34,12 @@ describe Patron::Request do
|
|
34
34
|
|
35
35
|
it "should accept :get, :put, :post, :delete and :head" do
|
36
36
|
[:get, :put, :post, :delete, :head, :copy].each do |action|
|
37
|
-
|
37
|
+
expect {@request.action = action}.not_to raise_error
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should raise an exception when assigned a bad value" do
|
42
|
-
|
42
|
+
expect {@request.action = :foo}.to raise_error(ArgumentError)
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
@@ -47,11 +47,11 @@ describe Patron::Request do
|
|
47
47
|
describe :timeout do
|
48
48
|
|
49
49
|
it "should raise an exception when assigned a negative number" do
|
50
|
-
|
50
|
+
expect {@request.timeout = -1}.to raise_error(ArgumentError)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should raise an exception when assigned 0" do
|
54
|
-
|
54
|
+
expect {@request.timeout = 0}.to raise_error(ArgumentError)
|
55
55
|
end
|
56
56
|
|
57
57
|
end
|
@@ -59,7 +59,7 @@ describe Patron::Request do
|
|
59
59
|
describe :max_redirects do
|
60
60
|
|
61
61
|
it "should raise an error when assigned an integer smaller than -1" do
|
62
|
-
|
62
|
+
expect {@request.max_redirects = -2}.to raise_error(ArgumentError)
|
63
63
|
end
|
64
64
|
|
65
65
|
end
|
@@ -67,7 +67,7 @@ describe Patron::Request do
|
|
67
67
|
describe :headers do
|
68
68
|
|
69
69
|
it "should raise an error when assigned something other than a hash" do
|
70
|
-
|
70
|
+
expect {@request.headers = :foo}.to raise_error(ArgumentError)
|
71
71
|
end
|
72
72
|
|
73
73
|
end
|
@@ -75,11 +75,11 @@ describe Patron::Request do
|
|
75
75
|
describe :buffer_size do
|
76
76
|
|
77
77
|
it "should raise an exception when assigned a negative number" do
|
78
|
-
|
78
|
+
expect {@request.buffer_size = -1}.to raise_error(ArgumentError)
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should raise an exception when assigned 0" do
|
82
|
-
|
82
|
+
expect {@request.buffer_size = 0}.to raise_error(ArgumentError)
|
83
83
|
end
|
84
84
|
|
85
85
|
end
|
@@ -87,18 +87,18 @@ describe Patron::Request do
|
|
87
87
|
describe :eql? do
|
88
88
|
|
89
89
|
it "should return true when two requests are equal" do
|
90
|
-
@request.
|
90
|
+
expect(@request).to eql(Patron::Request.new)
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should return false when two requests are not equal" do
|
94
94
|
req = Patron::Request.new
|
95
95
|
req.action = :post
|
96
|
-
@request.
|
96
|
+
expect(@request).not_to eql(req)
|
97
97
|
end
|
98
98
|
|
99
99
|
end
|
100
100
|
|
101
101
|
it "should be able to serialize and deserialize itself" do
|
102
|
-
Marshal.load(Marshal.dump(@request)).
|
102
|
+
expect(Marshal.load(Marshal.dump(@request))).to eql(@request)
|
103
103
|
end
|
104
104
|
end
|
data/spec/response_spec.rb
CHANGED
@@ -35,28 +35,28 @@ describe Patron::Response do
|
|
35
35
|
it "should strip extra spaces from header values" do
|
36
36
|
response = @session.get("/test")
|
37
37
|
# All digits, no spaces
|
38
|
-
response.headers['Content-Length'].
|
38
|
+
expect(response.headers['Content-Length']).to match(/^\d+$/)
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should return an array of values when multiple header fields have same name" do
|
42
42
|
response = @session.get("/repetitiveheader")
|
43
|
-
response.headers['Set-Cookie'].
|
43
|
+
expect(response.headers['Set-Cookie']).to be == ["a=1","b=2"]
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should works with non-text files" do
|
47
47
|
response = @session.get("/picture")
|
48
|
-
response.headers['Content-Type'].
|
49
|
-
response.body.encoding.
|
48
|
+
expect(response.headers['Content-Type']).to be == 'image/png'
|
49
|
+
expect(response.body.encoding).to be == Encoding::ASCII_8BIT
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should not allow a default charset to be nil" do
|
53
|
-
Encoding.
|
53
|
+
allow(Encoding).to receive(:default_internal).and_return("UTF-8")
|
54
54
|
expect {
|
55
55
|
Patron::Response.new("url", "status", 0, "", "", nil)
|
56
56
|
}.to_not raise_error
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should be able to serialize and deserialize itself" do
|
60
|
-
Marshal.load(Marshal.dump(@request)).
|
60
|
+
expect(Marshal.load(Marshal.dump(@request))).to eql(@request)
|
61
61
|
end
|
62
62
|
end
|
data/spec/session_spec.rb
CHANGED
@@ -34,207 +34,218 @@ describe Patron::Session do
|
|
34
34
|
@session.base_url = "http://localhost:9001"
|
35
35
|
end
|
36
36
|
|
37
|
+
it "should work when forcing ipv4" do
|
38
|
+
@session.force_ipv4 = true
|
39
|
+
expect { @session.get("/test") }.to_not raise_error
|
40
|
+
end
|
41
|
+
|
37
42
|
it "should escape and unescape strings symetrically" do
|
38
43
|
string = "foo~bar baz/"
|
39
44
|
escaped = @session.escape(string)
|
40
45
|
unescaped = @session.unescape(escaped)
|
41
|
-
unescaped.
|
46
|
+
expect(unescaped).to be == string
|
42
47
|
end
|
43
48
|
|
44
49
|
it "should raise an error when passed an invalid action" do
|
45
|
-
|
50
|
+
expect { @session.request(:bogus, "/test", {}) }.to raise_error(ArgumentError)
|
46
51
|
end
|
47
52
|
|
48
53
|
it "should raise an error when no URL is provided" do
|
49
54
|
@session.base_url = nil
|
50
|
-
|
55
|
+
expect {@session.get(nil)}.to raise_error(ArgumentError)
|
51
56
|
end
|
52
57
|
|
53
58
|
it "should retrieve a url with :get" do
|
54
59
|
response = @session.get("/test")
|
55
60
|
body = YAML::load(response.body)
|
56
|
-
body.request_method.
|
61
|
+
expect(body.request_method).to be == "GET"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should use full base url" do
|
65
|
+
@session.base_url = "http://localhost:9001/api/v1"
|
66
|
+
response = @session.get("/test")
|
67
|
+
expect(response.url).to be == "http://localhost:9001/api/v1/test"
|
57
68
|
end
|
58
69
|
|
59
70
|
it 'should ignore #base_url when a full URL is provided' do
|
60
71
|
@session.base_url = "http://example.com:123"
|
61
|
-
|
72
|
+
expect { @session.get("http://localhost:9001/test") }.to_not raise_error(URI::InvalidURIError)
|
62
73
|
end
|
63
74
|
|
64
75
|
it "should download content with :get and a file path" do
|
65
76
|
tmpfile = "/tmp/patron_test.yaml"
|
66
77
|
response = @session.get_file "/test", tmpfile
|
67
|
-
response.body.
|
78
|
+
expect(response.body).to be_nil
|
68
79
|
body = YAML::load_file(tmpfile)
|
69
|
-
body.request_method.
|
80
|
+
expect(body.request_method).to be == "GET"
|
70
81
|
FileUtils.rm tmpfile
|
71
82
|
end
|
72
83
|
|
73
84
|
it "should download correctly(md5 ok) with get_file" do
|
74
85
|
tmpfile = "/tmp/picture"
|
75
86
|
response = @session.get_file "/picture", tmpfile
|
76
|
-
response.body.
|
77
|
-
File.size(File.join(File.dirname(__FILE__),"../pic.png")).
|
87
|
+
expect(response.body).to be_nil
|
88
|
+
expect(File.size(File.join(File.dirname(__FILE__),"../pic.png"))).to be == File.size(tmpfile)
|
78
89
|
FileUtils.rm tmpfile
|
79
90
|
end
|
80
91
|
|
81
92
|
it "should include custom headers in a request" do
|
82
93
|
response = @session.get("/test", {"User-Agent" => "PatronTest"})
|
83
94
|
body = YAML::load(response.body)
|
84
|
-
body.header["user-agent"].
|
95
|
+
expect(body.header["user-agent"]).to be == ["PatronTest"]
|
85
96
|
end
|
86
97
|
|
87
98
|
it "should include default headers in a request, if they were defined" do
|
88
99
|
@session.headers = {"User-Agent" => "PatronTest"}
|
89
100
|
response = @session.get("/test")
|
90
101
|
body = YAML::load(response.body)
|
91
|
-
body.header["user-agent"].
|
102
|
+
expect(body.header["user-agent"]).to be == ["PatronTest"]
|
92
103
|
end
|
93
104
|
|
94
105
|
it "should merge custom headers with session headers" do
|
95
106
|
@session.headers["X-Test"] = "Testing"
|
96
107
|
response = @session.get("/test", {"User-Agent" => "PatronTest"})
|
97
108
|
body = YAML::load(response.body)
|
98
|
-
body.header["user-agent"].
|
99
|
-
body.header["x-test"].
|
109
|
+
expect(body.header["user-agent"]).to be == ["PatronTest"]
|
110
|
+
expect(body.header["x-test"]).to be == ["Testing"]
|
100
111
|
end
|
101
112
|
|
102
113
|
it "should raise an exception on timeout" do
|
103
114
|
@session.timeout = 1
|
104
|
-
|
115
|
+
expect {@session.get("/timeout")}.to raise_error(Patron::TimeoutError)
|
105
116
|
end
|
106
117
|
|
107
118
|
it "should follow redirects by default" do
|
108
119
|
@session.max_redirects = 1
|
109
120
|
response = @session.get("/redirect")
|
110
121
|
body = YAML::load(response.body)
|
111
|
-
response.status.
|
112
|
-
body.path.
|
122
|
+
expect(response.status).to be == 200
|
123
|
+
expect(body.path).to be == "/test"
|
113
124
|
end
|
114
125
|
|
115
126
|
it "should include redirect count in response" do
|
116
127
|
@session.max_redirects = 1
|
117
128
|
response = @session.get("/redirect")
|
118
|
-
response.redirect_count.
|
129
|
+
expect(response.redirect_count).to be == 1
|
119
130
|
end
|
120
131
|
|
121
132
|
it "should not follow redirects when configured to do so" do
|
122
133
|
@session.max_redirects = 0
|
123
134
|
response = @session.get("/redirect")
|
124
|
-
response.status.
|
125
|
-
response.body.
|
135
|
+
expect(response.status).to be == 301
|
136
|
+
expect(response.body).to be_empty
|
126
137
|
end
|
127
138
|
|
128
139
|
it "should retrieve URL metadata with :head" do
|
129
140
|
response = @session.head("/test")
|
130
|
-
response.status.
|
131
|
-
response.body.
|
132
|
-
response.headers.
|
141
|
+
expect(response.status).to be == 200
|
142
|
+
expect(response.body).to be_empty
|
143
|
+
expect(response.headers).to_not be_empty
|
133
144
|
end
|
134
145
|
|
135
146
|
it "should send a delete request with :delete" do
|
136
147
|
response = @session.delete("/test")
|
137
148
|
body = YAML::load(response.body)
|
138
|
-
body.request_method.
|
149
|
+
expect(body.request_method).to be == "DELETE"
|
139
150
|
end
|
140
151
|
|
141
152
|
it "should send a COPY request with :copy" do
|
142
153
|
response = @session.copy("/test", "/test2")
|
143
154
|
body = YAML::load(response.body)
|
144
|
-
body.request_method.
|
155
|
+
expect(body.request_method).to be == "COPY"
|
145
156
|
end
|
146
157
|
|
147
158
|
it "should include a Destination header in COPY requests" do
|
148
159
|
response = @session.copy("/test", "/test2")
|
149
160
|
body = YAML::load(response.body)
|
150
|
-
body.header['destination'].first.
|
161
|
+
expect(body.header['destination'].first).to be == "/test2"
|
151
162
|
end
|
152
163
|
|
153
164
|
it "should upload data with :get" do
|
154
165
|
data = "upload data"
|
155
166
|
response = @session.request(:get, "/test", {}, :data => data)
|
156
167
|
body = YAML::load(response.body)
|
157
|
-
body.request_method.
|
158
|
-
body.header['content-length'].
|
168
|
+
expect(body.request_method).to be == "GET"
|
169
|
+
expect(body.header['content-length']).to be == [data.size.to_s]
|
159
170
|
end
|
160
171
|
|
161
172
|
it "should upload data with :put" do
|
162
173
|
data = "upload data"
|
163
174
|
response = @session.put("/test", data)
|
164
175
|
body = YAML::load(response.body)
|
165
|
-
body.request_method.
|
166
|
-
body.header['content-length'].
|
176
|
+
expect(body.request_method).to be == "PUT"
|
177
|
+
expect(body.header['content-length']).to be == [data.size.to_s]
|
167
178
|
end
|
168
179
|
|
169
180
|
it "should upload data with :delete" do
|
170
181
|
data = "upload data"
|
171
182
|
response = @session.request(:delete, "/test", {}, :data => data)
|
172
183
|
body = YAML::load(response.body)
|
173
|
-
body.request_method.
|
174
|
-
body.header['content-length'].
|
184
|
+
expect(body.request_method).to be == "DELETE"
|
185
|
+
expect(body.header['content-length']).to be == [data.size.to_s]
|
175
186
|
end
|
176
187
|
|
177
188
|
it "should raise when no data is provided to :put" do
|
178
|
-
|
189
|
+
expect { @session.put("/test", nil) }.to raise_error(ArgumentError)
|
179
190
|
end
|
180
191
|
|
181
192
|
it "should upload a file with :put" do
|
182
193
|
response = @session.put_file("/test", "LICENSE")
|
183
194
|
body = YAML::load(response.body)
|
184
|
-
body.request_method.
|
195
|
+
expect(body.request_method).to be == "PUT"
|
185
196
|
end
|
186
197
|
|
187
198
|
it "should raise when no file is provided to :put" do
|
188
|
-
|
199
|
+
expect { @session.put_file("/test", nil) }.to raise_error(ArgumentError)
|
189
200
|
end
|
190
201
|
|
191
202
|
it "should use chunked encoding when uploading a file with :put" do
|
192
203
|
response = @session.put_file("/test", "LICENSE")
|
193
204
|
body = YAML::load(response.body)
|
194
|
-
body.header['transfer-encoding'].first.
|
205
|
+
expect(body.header['transfer-encoding'].first).to be == "chunked"
|
195
206
|
end
|
196
207
|
|
197
208
|
it "should upload data with :post" do
|
198
209
|
data = "upload data"
|
199
210
|
response = @session.post("/test", data)
|
200
211
|
body = YAML::load(response.body)
|
201
|
-
body.request_method.
|
202
|
-
body.header['content-length'].
|
212
|
+
expect(body.request_method).to be == "POST"
|
213
|
+
expect(body.header['content-length']).to be == [data.size.to_s]
|
203
214
|
end
|
204
215
|
|
205
216
|
it "should post a hash of arguments as a urlencoded form" do
|
206
217
|
data = {:foo => 123, 'baz' => '++hello world++'}
|
207
218
|
response = @session.post("/testpost", data)
|
208
219
|
body = YAML::load(response.body)
|
209
|
-
body['content_type'].
|
210
|
-
body['body'].
|
211
|
-
body['body'].
|
220
|
+
expect(body['content_type']).to be == "application/x-www-form-urlencoded"
|
221
|
+
expect(body['body']).to match(/baz=%2B%2Bhello%20world%2B%2B/)
|
222
|
+
expect(body['body']).to match(/foo=123/)
|
212
223
|
end
|
213
224
|
|
214
225
|
it "should raise when no data is provided to :post" do
|
215
|
-
|
226
|
+
expect { @session.post("/test", nil) }.to raise_error(ArgumentError)
|
216
227
|
end
|
217
228
|
|
218
229
|
it "should upload a file with :post" do
|
219
230
|
response = @session.post_file("/test", "LICENSE")
|
220
231
|
body = YAML::load(response.body)
|
221
|
-
body.request_method.
|
232
|
+
expect(body.request_method).to be == "POST"
|
222
233
|
end
|
223
234
|
|
224
235
|
it "should upload a multipart with :post" do
|
225
236
|
response = @session.post_multipart("/test", { :test_data => "123" }, { :test_file => "LICENSE" } )
|
226
237
|
body = YAML::load(response.body)
|
227
|
-
body.request_method.
|
238
|
+
expect(body.request_method).to be == "POST"
|
228
239
|
end
|
229
240
|
|
230
241
|
it "should raise when no file is provided to :post" do
|
231
|
-
|
242
|
+
expect { @session.post_file("/test", nil) }.to raise_error(ArgumentError)
|
232
243
|
end
|
233
244
|
|
234
245
|
it "should use chunked encoding when uploading a file with :post" do
|
235
246
|
response = @session.post_file("/test", "LICENSE")
|
236
247
|
body = YAML::load(response.body)
|
237
|
-
body.header['transfer-encoding'].first.
|
248
|
+
expect(body.header['transfer-encoding'].first).to be == "chunked"
|
238
249
|
end
|
239
250
|
|
240
251
|
it "should pass credentials as http basic auth" do
|
@@ -242,36 +253,36 @@ describe Patron::Session do
|
|
242
253
|
@session.password = "bar"
|
243
254
|
response = @session.get("/test")
|
244
255
|
body = YAML::load(response.body)
|
245
|
-
body.header['authorization'].
|
256
|
+
expect(body.header['authorization']).to be == [encode_authz("foo", "bar")]
|
246
257
|
end
|
247
258
|
|
248
259
|
it "should handle cookies if set" do
|
249
260
|
@session.handle_cookies
|
250
261
|
response = @session.get("/setcookie").body
|
251
|
-
YAML::load(response).header['cookie'].first.
|
262
|
+
expect(YAML::load(response).header['cookie'].first).to be == "session_id=foo123"
|
252
263
|
end
|
253
264
|
|
254
265
|
it "should not handle cookies by default" do
|
255
266
|
response = @session.get("/setcookie").body
|
256
|
-
YAML::load(response).header.
|
267
|
+
expect(YAML::load(response).header).to_not include('cookie')
|
257
268
|
end
|
258
269
|
|
259
270
|
it "should ignore a wrong Content-Length when asked to" do
|
260
|
-
|
271
|
+
expect {
|
261
272
|
@session.ignore_content_length = true
|
262
273
|
@session.get("/wrongcontentlength")
|
263
|
-
}.
|
274
|
+
}.to_not raise_error
|
264
275
|
end
|
265
276
|
|
266
277
|
it "should fail by default with a Content-Length too high" do
|
267
|
-
|
278
|
+
expect {
|
268
279
|
@session.ignore_content_length = nil
|
269
280
|
@session.get("/wrongcontentlength")
|
270
|
-
}.
|
281
|
+
}.to raise_error(Patron::PartialFileError)
|
271
282
|
end
|
272
283
|
|
273
284
|
it "should raise exception if cookie store is not writable or readable" do
|
274
|
-
|
285
|
+
expect { @session.handle_cookies("/trash/clash/foo") }.to raise_error(ArgumentError)
|
275
286
|
end
|
276
287
|
|
277
288
|
it "should work with multiple threads" do
|
@@ -296,42 +307,109 @@ describe Patron::Session do
|
|
296
307
|
|
297
308
|
body = nil
|
298
309
|
|
299
|
-
|
310
|
+
expect {
|
300
311
|
response = @session.get("/test")
|
301
312
|
body = YAML::load(response.body)
|
302
|
-
}.
|
313
|
+
}.to_not raise_error
|
303
314
|
|
304
|
-
body.request_method.
|
315
|
+
expect(body.request_method).to be == "GET"
|
305
316
|
end
|
306
317
|
|
307
318
|
it "should serialize query params and append them to the url" do
|
308
319
|
response = @session.request(:get, "/test", {}, :query => {:foo => "bar"})
|
309
320
|
request = YAML::load(response.body)
|
310
321
|
request.parse
|
311
|
-
(request.path + '?' + request.query_string).
|
322
|
+
expect(request.path + '?' + request.query_string).to be == "/test?foo=bar"
|
312
323
|
end
|
313
324
|
|
314
325
|
it "should merge parameters in the :query option with pre-existing query parameters" do
|
315
326
|
response = @session.request(:get, "/test?foo=bar", {}, :query => {:baz => "quux"})
|
316
327
|
request = YAML::load(response.body)
|
317
328
|
request.parse
|
318
|
-
(request.path + '?' + request.query_string).
|
329
|
+
expect(request.path + '?' + request.query_string).to be == "/test?foo=bar&baz=quux"
|
319
330
|
end
|
320
331
|
|
321
332
|
def encode_authz(user, passwd)
|
322
333
|
"Basic " + Base64.encode64("#{user}:#{passwd}").strip
|
323
334
|
end
|
324
335
|
|
336
|
+
describe 'when instantiating with hash arguments' do
|
337
|
+
|
338
|
+
let(:args) { {
|
339
|
+
:timeout => 10,
|
340
|
+
:base_url => 'http://localhost:9001',
|
341
|
+
:headers => {'User-Agent' => 'myapp/1.0'}
|
342
|
+
} }
|
343
|
+
|
344
|
+
let(:session) { Patron::Session.new(args) }
|
345
|
+
|
346
|
+
it 'sets the base_url' do
|
347
|
+
expect(session.base_url).to be == args[:base_url]
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'sets timeout' do
|
351
|
+
expect(session.timeout).to be == args[:timeout]
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'sets headers' do
|
355
|
+
expect(session.headers).to be == args[:headers]
|
356
|
+
end
|
357
|
+
|
358
|
+
context 'when given an incorrect accessor name' do
|
359
|
+
let(:args) { { :not_a_real_accessor => 'http://localhost:9001' }}
|
360
|
+
it 'raises no method error' do
|
361
|
+
expect { session }.to raise_error NoMethodError
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
describe 'when instantiating with a block' do
|
368
|
+
args = {
|
369
|
+
:timeout => 10,
|
370
|
+
:base_url => 'http://localhost:9001',
|
371
|
+
:headers => {'User-Agent' => 'myapp/1.0'}
|
372
|
+
}
|
373
|
+
|
374
|
+
session = Patron::Session.new do |patron|
|
375
|
+
patron.timeout = args[:timeout]
|
376
|
+
patron.base_url = args[:base_url]
|
377
|
+
patron.headers = args[:headers]
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'sets the base_url' do
|
381
|
+
expect(session.base_url).to be == args[:base_url]
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'sets timeout' do
|
385
|
+
expect(session.timeout).to be == args[:timeout]
|
386
|
+
end
|
387
|
+
|
388
|
+
it 'sets headers' do
|
389
|
+
expect(session.headers).to be == args[:headers]
|
390
|
+
end
|
391
|
+
|
392
|
+
context 'when given an incorrect accessor name' do
|
393
|
+
it 'raises no method error' do
|
394
|
+
expect {
|
395
|
+
Patron::Session.new do |patron|
|
396
|
+
patron.timeoutttt = args[:timeout]
|
397
|
+
end
|
398
|
+
}.to raise_error NoMethodError
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
325
403
|
# ------------------------------------------------------------------------
|
326
404
|
describe 'when debug is enabled' do
|
327
405
|
it 'it should not clobber stderr' do
|
328
406
|
rdev = STDERR.stat.rdev
|
329
407
|
|
330
408
|
@session.enable_debug
|
331
|
-
STDERR.stat.rdev.
|
409
|
+
expect(STDERR.stat.rdev).to be == rdev
|
332
410
|
|
333
411
|
@session.enable_debug
|
334
|
-
STDERR.stat.rdev.
|
412
|
+
expect(STDERR.stat.rdev).to be == rdev
|
335
413
|
end
|
336
414
|
end
|
337
415
|
|