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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 018a03fb6977a92e0dbf70f4e8473ef273d7576c
4
- data.tar.gz: 611bde5b709c9f24007fa8805b369310baa8ed6d
3
+ metadata.gz: c0a3e8dc6975392e43cac53cb03387ef07c3cab3
4
+ data.tar.gz: c58f5c72242c526bd2b8a9a70f13fa53248512e4
5
5
  SHA512:
6
- metadata.gz: a2e176e3648ab4293bc69cbaca8e048ba7effb544ebf49de0cd3647b99cd1105e0b52f1afaef32e3c9ab899ff5c41cc01e8fa2d97861de0f3064c405d0af4865
7
- data.tar.gz: a1525278695ce34f891f3d06f2bb352e841d97fba8b4f50b71a21b6fe960964cd4f8f9e39ca5dab1d65ac8d30e8fd97dd80b8d3c9ff8cc63d78eb331756c35df
6
+ metadata.gz: d4e0312f0cf82ed1db7d980bd93771016e710e7d2b1c6c3b7d7eaf965ff654eba61199eaa6a54df44e9c9ece0f610a8b16eb4bde37fce15b84fb733abf61f531
7
+ data.tar.gz: 28e92d83ad9d9e7e173c327c7797b6d11240e41c1fceadb4e3cfdbc9a35abe0597150c2ab32626d183992ec835d5bfd1a6c771df506e10b2fe44c9ca3ada15d1
@@ -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
- struct curl_state *state = get_curl_state(self);
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);
@@ -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
@@ -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
@@ -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 = CGI::escape(v.to_s) if escape_values
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
@@ -1,3 +1,3 @@
1
1
  module Patron
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -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
- it "should escape and unescape strings symetrically" do
43
- string = "foo~bar baz/"
44
- escaped = @session.escape(string)
45
- unescaped = @session.unescape(escaped)
46
- expect(unescaped).to be == string
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)
@@ -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
 
@@ -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.5.1
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-03-14 00:00:00.000000000 Z
11
+ date: 2016-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler