patron 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/patron/session_ext.c +18 -2
- data/lib/patron/request.rb +2 -2
- data/lib/patron/session.rb +4 -0
- data/lib/patron/util.rb +1 -3
- data/lib/patron/version.rb +1 -1
- data/spec/session_spec.rb +34 -7
- data/spec/support/test_server.rb +24 -3
- data/spec/util_spec.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0a3e8dc6975392e43cac53cb03387ef07c3cab3
|
4
|
+
data.tar.gz: c58f5c72242c526bd2b8a9a70f13fa53248512e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4e0312f0cf82ed1db7d980bd93771016e710e7d2b1c6c3b7d7eaf965ff654eba61199eaa6a54df44e9c9ece0f610a8b16eb4bde37fce15b84fb733abf61f531
|
7
|
+
data.tar.gz: 28e92d83ad9d9e7e173c327c7797b6d11240e41c1fceadb4e3cfdbc9a35abe0597150c2ab32626d183992ec835d5bfd1a6c771df506e10b2fe44c9ca3ada15d1
|
data/ext/patron/session_ext.c
CHANGED
@@ -223,16 +223,18 @@ static VALUE libcurl_version(VALUE klass) {
|
|
223
223
|
* URL escapes the provided string.
|
224
224
|
*/
|
225
225
|
static VALUE session_escape(VALUE self, VALUE value) {
|
226
|
-
|
226
|
+
|
227
227
|
VALUE string = StringValue(value);
|
228
228
|
char* escaped = NULL;
|
229
229
|
VALUE retval = Qnil;
|
230
230
|
|
231
|
+
struct curl_state* state = curl_easy_init();
|
231
232
|
escaped = curl_easy_escape(state->handle,
|
232
233
|
RSTRING_PTR(string),
|
233
234
|
(int) RSTRING_LEN(string));
|
234
235
|
|
235
236
|
retval = rb_str_new2(escaped);
|
237
|
+
curl_easy_cleanup(state);
|
236
238
|
curl_free(escaped);
|
237
239
|
|
238
240
|
return retval;
|
@@ -244,11 +246,11 @@ static VALUE session_escape(VALUE self, VALUE value) {
|
|
244
246
|
* Unescapes the provided string.
|
245
247
|
*/
|
246
248
|
static VALUE session_unescape(VALUE self, VALUE value) {
|
247
|
-
struct curl_state *state = get_curl_state(self);
|
248
249
|
VALUE string = StringValue(value);
|
249
250
|
char* unescaped = NULL;
|
250
251
|
VALUE retval = Qnil;
|
251
252
|
|
253
|
+
struct curl_state* state = curl_easy_init();
|
252
254
|
unescaped = curl_easy_unescape(state->handle,
|
253
255
|
RSTRING_PTR(string),
|
254
256
|
(int) RSTRING_LEN(string),
|
@@ -256,6 +258,7 @@ static VALUE session_unescape(VALUE self, VALUE value) {
|
|
256
258
|
|
257
259
|
retval = rb_str_new2(unescaped);
|
258
260
|
curl_free(unescaped);
|
261
|
+
curl_easy_cleanup(state);
|
259
262
|
|
260
263
|
return retval;
|
261
264
|
}
|
@@ -347,6 +350,7 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
347
350
|
VALUE ssl_version = Qnil;
|
348
351
|
VALUE buffer_size = Qnil;
|
349
352
|
VALUE action_name = rb_iv_get(request, "@action");
|
353
|
+
VALUE a_c_encoding = rb_iv_get(request, "@automatic_content_encoding");
|
350
354
|
|
351
355
|
headers = rb_iv_get(request, "@headers");
|
352
356
|
if (!NIL_P(headers)) {
|
@@ -454,6 +458,12 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
454
458
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->headers);
|
455
459
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, state->error_buf);
|
456
460
|
|
461
|
+
// Enable automatic content-encoding support via gzip/deflate if set in the request,
|
462
|
+
// see https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html
|
463
|
+
if(RTEST(a_c_encoding)) {
|
464
|
+
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
465
|
+
}
|
466
|
+
|
457
467
|
url = rb_iv_get(request, "@url");
|
458
468
|
if (NIL_P(url)) {
|
459
469
|
rb_raise(rb_eArgError, "Must provide a URL");
|
@@ -777,8 +787,14 @@ void Init_session_ext() {
|
|
777
787
|
cRequest = rb_define_class_under(mPatron, "Request", rb_cObject);
|
778
788
|
rb_define_alloc_func(cSession, session_alloc);
|
779
789
|
|
790
|
+
// Make "escape" available both as a class method and as an instance method,
|
791
|
+
// to make it usable to the Util module which does not have access to
|
792
|
+
// the Session object internally
|
793
|
+
rb_define_singleton_method(cSession, "escape", session_escape, 1);
|
780
794
|
rb_define_method(cSession, "escape", session_escape, 1);
|
795
|
+
rb_define_singleton_method(cSession, "unescape", session_unescape, 1);
|
781
796
|
rb_define_method(cSession, "unescape", session_unescape, 1);
|
797
|
+
|
782
798
|
rb_define_method(cSession, "handle_request", session_handle_request, 1);
|
783
799
|
rb_define_method(cSession, "reset", session_reset, 0);
|
784
800
|
rb_define_method(cSession, "interrupt", session_interrupt, 0);
|
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, :force_ipv4
|
49
|
+
:ssl_version, :automatic_content_encoding, :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, :force_ipv4
|
54
|
+
:ignore_content_length, :multipart, :cacert, :ssl_version, :automatic_content_encoding, :force_ipv4
|
55
55
|
]
|
56
56
|
|
57
57
|
attr_reader *READER_VARS
|
data/lib/patron/session.rb
CHANGED
@@ -87,6 +87,9 @@ module Patron
|
|
87
87
|
# Force curl to use IPv4
|
88
88
|
attr_accessor :force_ipv4
|
89
89
|
|
90
|
+
# Support automatic Content-Encoding decompression and set liberal Accept-Encoding headers
|
91
|
+
attr_accessor :automatic_content_encoding
|
92
|
+
|
90
93
|
private :handle_request, :enable_cookie_session, :set_debug_file
|
91
94
|
|
92
95
|
# Create a new Session object.
|
@@ -236,6 +239,7 @@ module Patron
|
|
236
239
|
Request.new.tap do |req|
|
237
240
|
req.action = action
|
238
241
|
req.headers = self.headers.merge headers
|
242
|
+
req.automatic_content_encoding = options.fetch :automatic_content_encoding, self.automatic_content_encoding
|
239
243
|
req.timeout = options.fetch :timeout, self.timeout
|
240
244
|
req.connect_timeout = options.fetch :connect_timeout, self.connect_timeout
|
241
245
|
req.force_ipv4 = options.fetch :force_ipv4, self.force_ipv4
|
data/lib/patron/util.rb
CHANGED
@@ -23,8 +23,6 @@
|
|
23
23
|
##
|
24
24
|
## -------------------------------------------------------------------
|
25
25
|
|
26
|
-
require 'cgi'
|
27
|
-
|
28
26
|
module Patron
|
29
27
|
module Util
|
30
28
|
extend self
|
@@ -34,7 +32,7 @@ module Patron
|
|
34
32
|
recursive = Proc.new do |h, prefix|
|
35
33
|
h.each_pair do |k,v|
|
36
34
|
key = prefix == '' ? k : "#{prefix}[#{k}]"
|
37
|
-
v =
|
35
|
+
v = Patron::Session.escape(v.to_s) if escape_values
|
38
36
|
v.is_a?(Hash) ? recursive.call(v, key) : pairs << "#{key}=#{v}"
|
39
37
|
end
|
40
38
|
end
|
data/lib/patron/version.rb
CHANGED
data/spec/session_spec.rb
CHANGED
@@ -38,14 +38,30 @@ describe Patron::Session do
|
|
38
38
|
@session.force_ipv4 = true
|
39
39
|
expect { @session.get("/test") }.to_not raise_error
|
40
40
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
|
42
|
+
describe '.escape and #escape' do
|
43
|
+
it 'makes escape() and unescape() available on the class' do
|
44
|
+
string = "foo~bar baz/"
|
45
|
+
escaped = described_class.escape(string)
|
46
|
+
unescaped = described_class.unescape(escaped)
|
47
|
+
expect(unescaped).to be == string
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should escape and unescape strings symetrically" do
|
51
|
+
string = "foo~bar baz/"
|
52
|
+
escaped = @session.escape(string)
|
53
|
+
unescaped = @session.unescape(escaped)
|
54
|
+
expect(unescaped).to be == string
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should make e and unescape strings symetrically" do
|
58
|
+
string = "foo~bar baz/"
|
59
|
+
escaped = @session.escape(string)
|
60
|
+
unescaped = @session.unescape(escaped)
|
61
|
+
expect(unescaped).to be == string
|
62
|
+
end
|
47
63
|
end
|
48
|
-
|
64
|
+
|
49
65
|
it "should raise an error when passed an invalid action" do
|
50
66
|
expect { @session.request(:bogus, "/test", {}) }.to raise_error(ArgumentError)
|
51
67
|
end
|
@@ -329,6 +345,17 @@ describe Patron::Session do
|
|
329
345
|
expect(body.request_method).to be == "GET"
|
330
346
|
end
|
331
347
|
|
348
|
+
it "should automatically decompress using Content-Encoding if requested" do
|
349
|
+
@session.automatic_content_encoding = true
|
350
|
+
response = @session.get('/gzip-compressed')
|
351
|
+
|
352
|
+
expect(response.headers['Content-Length']).to eq('125')
|
353
|
+
|
354
|
+
body = response.body
|
355
|
+
expect(body).to match(/Some highly compressible data/)
|
356
|
+
expect(body.bytesize).to eq(29696)
|
357
|
+
end
|
358
|
+
|
332
359
|
it "should serialize query params and append them to the url" do
|
333
360
|
response = @session.request(:get, "/test", {}, :query => {:foo => "bar"})
|
334
361
|
request = YAML::load(response.body)
|
data/spec/support/test_server.rb
CHANGED
@@ -70,6 +70,29 @@ class TestServlet < HTTPServlet::AbstractServlet
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
class GzipServlet < HTTPServlet::AbstractServlet
|
74
|
+
|
75
|
+
def do_GET(req,res)
|
76
|
+
raise "Need to have the right Accept-Encoding: header" unless req.header['Accept-Encoding']
|
77
|
+
|
78
|
+
out = StringIO.new
|
79
|
+
z = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION)
|
80
|
+
1024.times {
|
81
|
+
out << z.deflate('Some highly compressible data')
|
82
|
+
}
|
83
|
+
out << z.finish
|
84
|
+
z.close
|
85
|
+
|
86
|
+
content_length = out.size
|
87
|
+
# Content-Length gets set automatically by WEBrick, and if we do it manually
|
88
|
+
# here then two headers will be set.
|
89
|
+
# res.header['Content-Length'] = content_length
|
90
|
+
res.header['Content-Encoding'] = 'deflate'
|
91
|
+
res.header['Vary'] = 'Accept-Encoding'
|
92
|
+
res.body = out.string
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
73
96
|
class TimeoutServlet < HTTPServlet::AbstractServlet
|
74
97
|
def do_GET(req,res)
|
75
98
|
sleep(1.1)
|
@@ -83,7 +106,6 @@ class RedirectServlet < HTTPServlet::AbstractServlet
|
|
83
106
|
end
|
84
107
|
end
|
85
108
|
|
86
|
-
|
87
109
|
class TestPostBodyServlet < HTTPServlet::AbstractServlet
|
88
110
|
include RespondWith
|
89
111
|
def do_POST(req, res)
|
@@ -91,8 +113,6 @@ class TestPostBodyServlet < HTTPServlet::AbstractServlet
|
|
91
113
|
end
|
92
114
|
end
|
93
115
|
|
94
|
-
|
95
|
-
|
96
116
|
class SetCookieServlet < HTTPServlet::AbstractServlet
|
97
117
|
def do_GET(req, res)
|
98
118
|
res['Set-Cookie'] = "session_id=foo123"
|
@@ -162,6 +182,7 @@ class PatronTestServer
|
|
162
182
|
@server.mount("/setcookie", SetCookieServlet)
|
163
183
|
@server.mount("/repetitiveheader", RepetitiveHeaderServlet)
|
164
184
|
@server.mount("/wrongcontentlength", WrongContentLengthServlet)
|
185
|
+
@server.mount("/gzip-compressed", GzipServlet)
|
165
186
|
|
166
187
|
end
|
167
188
|
|
data/spec/util_spec.rb
CHANGED
@@ -26,6 +26,7 @@ require File.expand_path("./spec") + '/spec_helper.rb'
|
|
26
26
|
describe Patron::Util do
|
27
27
|
|
28
28
|
describe :build_query_pairs_from_hash do
|
29
|
+
|
29
30
|
it "correctly serializes a simple hash" do
|
30
31
|
hash = {:foo => "bar", "baz" => 42}
|
31
32
|
array = Patron::Util.build_query_pairs_from_hash(hash)
|
@@ -33,6 +34,7 @@ describe Patron::Util do
|
|
33
34
|
expect(array).to include("foo=bar")
|
34
35
|
expect(array).to include("baz=42")
|
35
36
|
end
|
37
|
+
|
36
38
|
it "correctly serializes a more complex hash" do
|
37
39
|
hash = {
|
38
40
|
:foo => "bar",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phillip Toland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|