patron 0.5.1 → 0.6.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 +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
|