patron 0.4.20 → 0.5.0
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.
- 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
|
|