patron 0.4.18 → 0.4.20

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.
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- patron (0.4.18)
4
+ patron (0.4.20)
5
5
 
6
6
  GEM
7
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
8
8
  specs:
9
9
  diff-lcs (1.1.3)
10
10
  rake (0.9.2.2)
@@ -1,13 +1,13 @@
1
- = Ruby HTTP Client
1
+ # Ruby HTTP Client
2
2
 
3
- == SYNOPSIS
3
+ ## SYNOPSIS
4
4
 
5
5
  Patron is a Ruby HTTP client library based on libcurl. It does not try to expose
6
6
  the full "power" (read complexity) of libcurl but instead tries to provide a
7
7
  sane API while taking advantage of libcurl under the hood.
8
8
 
9
9
 
10
- == USAGE
10
+ ## USAGE
11
11
 
12
12
  Usage is very simple. First, you instantiate a Session object. You can set a few
13
13
  default options on the Session instance that will be used by all subsequent
@@ -41,7 +41,7 @@ You can ship custom headers with a single request:
41
41
  That is pretty much all there is to it.
42
42
 
43
43
 
44
- == REQUIREMENTS
44
+ ## REQUIREMENTS
45
45
 
46
46
  You need a recent version of libcurl in order to install this gem. On MacOS X
47
47
  the provided libcurl is sufficient. You will have to install the libcurl
@@ -49,9 +49,9 @@ development packages on Debian or Ubuntu. Other Linux systems are probably
49
49
  similar. Windows users are on your own. Good luck with that.
50
50
 
51
51
 
52
- == INSTALL
52
+ ## INSTALL
53
53
 
54
- sudo gem install patron
54
+ sudo gem install patron
55
55
 
56
56
 
57
57
  Copyright (c) 2008 The Hive
@@ -260,10 +260,25 @@ static VALUE session_unescape(VALUE self, VALUE value) {
260
260
  /* Callback used to iterate over the HTTP headers and store them in an slist. */
261
261
  static int each_http_header(VALUE header_key, VALUE header_value, VALUE self) {
262
262
  struct curl_state *state = get_curl_state(self);
263
+ CURL* curl = state->handle;
264
+
263
265
  VALUE name = rb_obj_as_string(header_key);
264
266
  VALUE value = rb_obj_as_string(header_value);
265
267
  VALUE header_str = Qnil;
266
268
 
269
+ if (rb_str_cmp(name, rb_str_new2("Accept-Encoding")) == 0) {
270
+ if (rb_funcall(value, rb_intern("include?"), 1, rb_str_new2("gzip"))) {
271
+ #ifdef CURLOPT_ACCEPT_ENCODING
272
+ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
273
+ #elif defined CURLOPT_ENCODING
274
+ curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");
275
+ #else
276
+ rb_raise(rb_eArgError,
277
+ "The libcurl version installed doesn't support 'gzip'.");
278
+ #endif
279
+ }
280
+ }
281
+
267
282
  header_str = rb_str_plus(name, rb_str_new2(": "));
268
283
  header_str = rb_str_plus(header_str, value);
269
284
 
@@ -325,7 +340,10 @@ static void set_options_from_request(VALUE self, VALUE request) {
325
340
  VALUE credentials = Qnil;
326
341
  VALUE ignore_content_length = Qnil;
327
342
  VALUE insecure = Qnil;
343
+ VALUE cacert = Qnil;
344
+ VALUE ssl_version = Qnil;
328
345
  VALUE buffer_size = Qnil;
346
+ VALUE action_name = rb_iv_get(request, "@action");
329
347
 
330
348
  headers = rb_iv_get(request, "@headers");
331
349
  if (!NIL_P(headers)) {
@@ -336,7 +354,8 @@ static void set_options_from_request(VALUE self, VALUE request) {
336
354
  rb_hash_foreach(headers, each_http_header, self);
337
355
  }
338
356
 
339
- action = SYM2ID(rb_iv_get(request, "@action"));
357
+ action = SYM2ID(action_name);
358
+
340
359
  if (action == rb_intern("get")) {
341
360
  VALUE data = rb_iv_get(request, "@upload_data");
342
361
  VALUE download_file = rb_iv_get(request, "@file_name");
@@ -352,7 +371,7 @@ static void set_options_from_request(VALUE self, VALUE request) {
352
371
  curl_easy_setopt(curl, CURLOPT_INFILESIZE, len);
353
372
  }
354
373
  if (!NIL_P(download_file)) {
355
- state->download_file = open_file(download_file, "w");
374
+ state->download_file = open_file(download_file, "wb");
356
375
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, state->download_file);
357
376
  } else {
358
377
  state->download_file = NULL;
@@ -386,7 +405,7 @@ static void set_options_from_request(VALUE self, VALUE request) {
386
405
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
387
406
  }
388
407
 
389
- state->upload_file = open_file(filename, "r");
408
+ state->upload_file = open_file(filename, "rb");
390
409
  curl_easy_setopt(curl, CURLOPT_READDATA, state->upload_file);
391
410
  } else if (!NIL_P(multipart)) {
392
411
  if (action == rb_intern("post")) {
@@ -405,6 +424,20 @@ static void set_options_from_request(VALUE self, VALUE request) {
405
424
  } else {
406
425
  rb_raise(rb_eArgError, "Must provide either data or a filename when doing a PUT or POST");
407
426
  }
427
+
428
+ // support for data passed with a DELETE request (e.g.: used by elasticsearch)
429
+ } else if (action == rb_intern("delete")) {
430
+ VALUE data = rb_iv_get(request, "@upload_data");
431
+
432
+ if (!NIL_P(data)) {
433
+ long len = RSTRING_LEN(data);
434
+ state->upload_buf = StringValuePtr(data);
435
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
436
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, state->upload_buf);
437
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
438
+ }
439
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
440
+
408
441
  } else if (action == rb_intern("head")) {
409
442
  curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
410
443
  } else {
@@ -440,7 +473,7 @@ static void set_options_from_request(VALUE self, VALUE request) {
440
473
 
441
474
  proxy = rb_iv_get(request, "@proxy");
442
475
  if (!NIL_P(proxy)) {
443
- curl_easy_setopt(curl, CURLOPT_PROXY, StringValuePtr(proxy));
476
+ curl_easy_setopt(curl, CURLOPT_PROXY, StringValuePtr(proxy));
444
477
  }
445
478
 
446
479
  proxy_type = rb_iv_get(request, "@proxy_type");
@@ -462,7 +495,24 @@ static void set_options_from_request(VALUE self, VALUE request) {
462
495
  insecure = rb_iv_get(request, "@insecure");
463
496
  if(!NIL_P(insecure)) {
464
497
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
465
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
498
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
499
+ }
500
+
501
+ ssl_version = rb_iv_get(request, "@ssl_version");
502
+ if(!NIL_P(ssl_version)) {
503
+ char* version = StringValuePtr(ssl_version);
504
+ if(strcmp(version, "SSLv2") == 0) {
505
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv2);
506
+ } else if(strcmp(version, "SSLv3") == 0) {
507
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
508
+ } else if(strcmp(version, "TLSv1") == 0) {
509
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
510
+ }
511
+ }
512
+
513
+ cacert = rb_iv_get(request, "@cacert");
514
+ if(!NIL_P(cacert)) {
515
+ curl_easy_setopt(curl, CURLOPT_CAINFO, StringValuePtr(cacert));
466
516
  }
467
517
 
468
518
  buffer_size = rb_iv_get(request, "@buffer_size");
@@ -672,7 +722,7 @@ static VALUE set_debug_file(VALUE self, VALUE file) {
672
722
  session_close_debug_file(state);
673
723
 
674
724
  if(file_path != NULL && strlen(file_path) != 0) {
675
- state->debug_file = open_file(file, "w");
725
+ state->debug_file = open_file(file, "wb");
676
726
  } else {
677
727
  state->debug_file = stderr;
678
728
  }
@@ -730,4 +780,3 @@ void Init_session_ext() {
730
780
  rb_define_const(mProxyType, "SOCKS4A", INT2FIX(CURLPROXY_SOCKS4A));
731
781
  rb_define_const(mProxyType, "SOCKS5_HOSTNAME", INT2FIX(CURLPROXY_SOCKS5_HOSTNAME));
732
782
  }
733
-
data/lib/patron.rb CHANGED
@@ -28,6 +28,7 @@ cwd = Pathname(__FILE__).dirname
28
28
  $:.unshift(cwd.to_s) unless $:.include?(cwd.to_s) || $:.include?(cwd.expand_path.to_s)
29
29
 
30
30
  require 'patron/session'
31
+ require 'patron/version'
31
32
 
32
33
  module Patron #:nodoc:
33
34
  # Returns the version number of the Patron library as a string
@@ -32,7 +32,7 @@ module Patron
32
32
  # used in every request.
33
33
  class Request
34
34
 
35
- VALID_ACTIONS = [:get, :put, :post, :delete, :head, :copy]
35
+ VALID_ACTIONS = %w[GET PUT POST DELETE HEAD COPY]
36
36
 
37
37
  def initialize
38
38
  @action = :get
@@ -42,9 +42,20 @@ module Patron
42
42
  @max_redirects = -1
43
43
  end
44
44
 
45
- attr_accessor :url, :username, :password, :file_name, :proxy, :proxy_type, :auth_type, :insecure, :ignore_content_length, :multipart
46
- attr_reader :action, :timeout, :connect_timeout, :max_redirects, :headers, :buffer_size
47
- attr_reader :auth_type
45
+ READER_VARS = [
46
+ :url, :username, :password, :file_name, :proxy, :proxy_type, :insecure,
47
+ :ignore_content_length, :multipart, :action, :timeout, :connect_timeout,
48
+ :max_redirects, :headers, :auth_type, :upload_data, :buffer_size, :cacert,
49
+ :ssl_version
50
+ ]
51
+
52
+ WRITER_VARS = [
53
+ :url, :username, :password, :file_name, :proxy, :proxy_type, :insecure,
54
+ :ignore_content_length, :multipart, :cacert, :ssl_version
55
+ ]
56
+
57
+ attr_reader *READER_VARS
58
+ attr_writer *WRITER_VARS
48
59
 
49
60
  # Set the type of authentication to use for this request.
50
61
  #
@@ -71,22 +82,17 @@ module Patron
71
82
  def upload_data=(data)
72
83
  @upload_data = case data
73
84
  when Hash
74
- self.multipart ? data : Util.build_query_string_from_hash(data, @action == :post)
85
+ self.multipart ? data : Util.build_query_string_from_hash(data, action == :post)
75
86
  else
76
87
  data
77
88
  end
78
89
  end
79
90
 
80
- def upload_data
81
- @upload_data
82
- end
83
-
84
- def action=(new_action)
85
- if !VALID_ACTIONS.include?(new_action)
91
+ def action=(action)
92
+ if !VALID_ACTIONS.include?(action.to_s.upcase)
86
93
  raise ArgumentError, "Action must be one of #{VALID_ACTIONS.join(', ')}"
87
94
  end
88
-
89
- @action = new_action
95
+ @action = action.downcase.to_sym
90
96
  end
91
97
 
92
98
  def timeout=(new_timeout)
@@ -129,13 +135,35 @@ module Patron
129
135
  @buffer_size = buffer_size != nil ? buffer_size.to_i : nil
130
136
  end
131
137
 
138
+ def credentials
139
+ return nil if username.nil? || password.nil?
140
+ "#{username}:#{password}"
141
+ end
142
+
132
143
  def action_name
133
144
  @action.to_s.upcase
134
145
  end
135
146
 
136
- def credentials
137
- return nil if username.nil? || password.nil?
138
- "#{username}:#{password}"
147
+ def eql?(request)
148
+ return false unless Request === request
149
+
150
+ READER_VARS.inject(true) do |memo, name|
151
+ memo && (self.send(name) == request.send(name))
152
+ end
153
+ end
154
+
155
+ alias_method :==, :eql?
156
+
157
+ def marshal_dump
158
+ [ @url, @username, @password, @file_name, @proxy, @proxy_type, @insecure,
159
+ @ignore_content_length, @multipart, @action, @timeout, @connect_timeout,
160
+ @max_redirects, @headers, @auth_type, @upload_data, @buffer_size, @cacert ]
161
+ end
162
+
163
+ def marshal_load(data)
164
+ @url, @username, @password, @file_name, @proxy, @proxy_type, @insecure,
165
+ @ignore_content_length, @multipart, @action, @timeout, @connect_timeout,
166
+ @max_redirects, @headers, @auth_type, @upload_data, @buffer_size, @cacert = data
139
167
  end
140
168
 
141
169
  end
@@ -35,13 +35,13 @@ module Patron
35
35
  @status = status
36
36
  @redirect_count = redirect_count
37
37
  @body = body
38
-
38
+
39
39
  @charset = determine_charset(header_data, body) || default_charset
40
-
40
+
41
41
  [url, header_data].each do |attr|
42
42
  convert_to_default_encoding!(attr)
43
43
  end
44
-
44
+
45
45
  parse_headers(header_data)
46
46
  if @headers["Content-Type"] && @headers["Content-Type"][0, 5] == "text/"
47
47
  convert_to_default_encoding!(@body)
@@ -55,14 +55,22 @@ module Patron
55
55
  "#<Patron::Response @status_line='#{@status_line}'>"
56
56
  end
57
57
 
58
+ def marshal_dump
59
+ [@url, @status, @status_line, @redirect_count, @body, @headers, @charset]
60
+ end
61
+
62
+ def marshal_load(data)
63
+ @url, @status, @status_line, @redirect_count, @body, @headers, @charset = data
64
+ end
65
+
58
66
  private
59
67
 
60
68
  def determine_charset(header_data, body)
61
69
  header_data.match(charset_regex) || (body && body.match(charset_regex))
62
-
70
+
63
71
  $1
64
72
  end
65
-
73
+
66
74
  def charset_regex
67
75
  /(?:charset|encoding)="?([a-z0-9-]+)"?/i
68
76
  end
@@ -59,7 +59,7 @@ module Patron
59
59
  attr_accessor :proxy_type
60
60
 
61
61
  # Standard set of headers that are used in all requests.
62
- attr_reader :headers
62
+ attr_accessor :headers
63
63
 
64
64
  # Set the authentication type for the request.
65
65
  # @see Patron::Request#auth_type
@@ -68,6 +68,12 @@ module Patron
68
68
  # Does this session stricly verify SSL certificates?
69
69
  attr_accessor :insecure
70
70
 
71
+ # Specifies the ssl version
72
+ attr_accessor :ssl_version
73
+
74
+ # What cacert file should this session use to verify SSL certificates?
75
+ attr_accessor :cacert
76
+
71
77
  # Does this session ignore Content-Size headers?
72
78
  attr_accessor :ignore_content_length
73
79
 
@@ -138,6 +144,8 @@ module Patron
138
144
  end
139
145
 
140
146
  # As #get but sends an HTTP DELETE request.
147
+ # Notice: this method doesn't accept any +data+ argument: if you need to send data with
148
+ # a delete request, please, use the #request method.
141
149
  def delete(url, headers = {})
142
150
  request(:delete, url, headers)
143
151
  end
@@ -189,39 +197,46 @@ module Patron
189
197
 
190
198
  # Send an HTTP request to the specified +url+.
191
199
  def request(action, url, headers, options = {})
200
+ req = build_request(action, url, headers, options)
201
+ handle_request(req)
202
+ end
203
+
204
+ # Build a request object that can be used in +handle_request+
205
+ def build_request(action, url, headers, options = {})
192
206
  # If the Expect header isn't set uploads are really slow
193
207
  headers['Expect'] ||= ''
194
208
 
195
- req = Request.new
196
- req.action = action
197
- req.headers = self.headers.merge headers
198
- req.timeout = options.fetch :timeout, self.timeout
199
- req.connect_timeout = options.fetch :connect_timeout, self.connect_timeout
200
- req.max_redirects = options.fetch :max_redirects, self.max_redirects
201
- req.username = options.fetch :username, self.username
202
- req.password = options.fetch :password, self.password
203
- req.proxy = options.fetch :proxy, self.proxy
204
- req.proxy_type = options.fetch :proxy_type, self.proxy_type
205
- req.auth_type = options.fetch :auth_type, self.auth_type
206
- req.insecure = options.fetch :insecure, self.insecure
207
- req.ignore_content_length = options.fetch :ignore_content_length, self.ignore_content_length
208
- req.buffer_size = options.fetch :buffer_size, self.buffer_size
209
- req.multipart = options[:multipart]
210
- req.upload_data = options[:data]
211
- req.file_name = options[:file]
212
-
213
- url = self.base_url.to_s + url.to_s
214
- uri = URI.parse(url)
215
- query = uri.query.to_s.split('&')
216
- query += options[:query].is_a?(Hash) ? Util.build_query_pairs_from_hash(options[:query]) : options[:query].to_s.split('&')
217
- uri.query = query.join('&')
218
- uri.query = nil if uri.query.empty?
219
- url = uri.to_s
220
- raise ArgumentError, "Empty URL" if url.empty?
221
- req.url = url
222
-
223
- handle_request(req)
209
+ Request.new.tap do |req|
210
+ req.action = action
211
+ req.headers = self.headers.merge headers
212
+ req.timeout = options.fetch :timeout, self.timeout
213
+ req.connect_timeout = options.fetch :connect_timeout, self.connect_timeout
214
+ req.max_redirects = options.fetch :max_redirects, self.max_redirects
215
+ req.username = options.fetch :username, self.username
216
+ req.password = options.fetch :password, self.password
217
+ req.proxy = options.fetch :proxy, self.proxy
218
+ req.proxy_type = options.fetch :proxy_type, self.proxy_type
219
+ req.auth_type = options.fetch :auth_type, self.auth_type
220
+ req.insecure = options.fetch :insecure, self.insecure
221
+ req.ssl_version = options.fetch :ssl_version, self.ssl_version
222
+ req.cacert = options.fetch :cacert, self.cacert
223
+ req.ignore_content_length = options.fetch :ignore_content_length, self.ignore_content_length
224
+ req.buffer_size = options.fetch :buffer_size, self.buffer_size
225
+ req.multipart = options[:multipart]
226
+ req.upload_data = options[:data]
227
+ req.file_name = options[:file]
228
+
229
+ base_url = self.base_url.to_s
230
+ url = url.to_s
231
+ raise ArgumentError, "Empty URL" if base_url.empty? && url.empty?
232
+ uri = URI.join(base_url, url)
233
+ query = uri.query.to_s.split('&')
234
+ query += options[:query].is_a?(Hash) ? Util.build_query_pairs_from_hash(options[:query]) : options[:query].to_s.split('&')
235
+ uri.query = query.join('&')
236
+ uri.query = nil if uri.query.empty?
237
+ url = uri.to_s
238
+ req.url = url
239
+ end
224
240
  end
225
-
226
241
  end
227
242
  end
@@ -1,3 +1,3 @@
1
1
  module Patron
2
- VERSION = "0.4.18"
2
+ VERSION = "0.4.20"
3
3
  end
@@ -0,0 +1,36 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
35
+ djS6lZ9vTEbRM+GhU2PMKfvJbiQ/Y6Q=
36
+ -----END CERTIFICATE-----
@@ -0,0 +1,51 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ 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
38
+ Tmsg4oRHzfquVnr6GK6x7ZHIo5mpHHHdOiyp/UD+anfbbMRItcHkzHDctkaoOKWI
39
+ h3P0mYZ5LIJNVuErhucrP57tr+bOOttus9HLHXTYsjOGV4zSKUSVQTOxnTzZepd8
40
+ zIdo+wKCAQAg/Z80RPYGd/IVmD0NWxDbRhfEXn37XhRr1eIfNLjpktMGQENSiPEI
41
+ FM12S+xSUOC31Hs5u+BNop1kCfd1yuf4NxC8eyMjKO3tM90wc+KUMLeh9TdPZ96J
42
+ dD96eVftTuavTkdFZdWB8wSwxDZX3uV4ir1t6bIKDoyz+yqYM3v3HfweJIq0ox2p
43
+ TS40cDDWnt/ZIk3TyMS1QPWbr0Jl8or0JYmRVp1m8jiDwcsp9tUd9+/5bgKhC3uM
44
+ tY0HjOULzvvHkkul5ADAHyNS7zq9lEwEhIilkhX3M0wX3ZxvXwJPUbgYurcbNmgd
45
+ imp6DpuPJPdbg/8bz9YiaAZOnObnE9lFAoIBAGIdAhDDhqhPIW3xDx54TBfxQFi+
46
+ CeFw1g2duwXAXkBV98nKeLdTo3tL8gusb+32LzgVIq2spWUN72xXX40NJjW1Bxk5
47
+ SGatM1T13BaUFNYtzpM9arDPNr3tCiCSzeVvMKdLfp+Vx9R9arnOgLlGkhRCdEtb
48
+ lXAteE7Twuztvad/M0LGpbjN6BD23KLOfxx9C2TgfMuK/Fjt71ASV+80cq4SS2WK
49
+ fqZQnKfGIRE8wcY2R5g2AwEzubCRzD93pGG3KleQKxrUKNoV32M2ZZcM04l8woZX
50
+ vrkNxM3gbBkhFPAJ9LrmA4YExODUXzWt6Y2mCXuH2Ly60yiLa66HbEfhHrs=
51
+ -----END RSA PRIVATE KEY-----
data/spec/request_spec.rb CHANGED
@@ -83,4 +83,22 @@ describe Patron::Request do
83
83
  end
84
84
 
85
85
  end
86
+
87
+ describe :eql? do
88
+
89
+ it "should return true when two requests are equal" do
90
+ @request.should eql(Patron::Request.new)
91
+ end
92
+
93
+ it "should return false when two requests are not equal" do
94
+ req = Patron::Request.new
95
+ req.action = :post
96
+ @request.should_not eql(req)
97
+ end
98
+
99
+ end
100
+
101
+ it "should be able to serialize and deserialize itself" do
102
+ Marshal.load(Marshal.dump(@request)).should eql(@request)
103
+ end
86
104
  end
@@ -48,11 +48,15 @@ describe Patron::Response do
48
48
  response.headers['Content-Type'].should == 'image/png'
49
49
  response.body.encoding.should == Encoding::ASCII_8BIT
50
50
  end
51
-
51
+
52
52
  it "should not allow a default charset to be nil" do
53
53
  Encoding.stub(: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
+
59
+ it "should be able to serialize and deserialize itself" do
60
+ Marshal.load(Marshal.dump(@request)).should eql(@request)
61
+ end
58
62
  end
data/spec/session_spec.rb CHANGED
@@ -56,6 +56,11 @@ describe Patron::Session do
56
56
  body.request_method.should == "GET"
57
57
  end
58
58
 
59
+ it 'should ignore #base_url when a full URL is provided' do
60
+ @session.base_url = "http://example.com:123"
61
+ lambda { @session.get("http://localhost:9001/test") }.should_not raise_error(URI::InvalidURIError)
62
+ end
63
+
59
64
  it "should download content with :get and a file path" do
60
65
  tmpfile = "/tmp/patron_test.yaml"
61
66
  response = @session.get_file "/test", tmpfile
@@ -65,12 +70,27 @@ describe Patron::Session do
65
70
  FileUtils.rm tmpfile
66
71
  end
67
72
 
73
+ it "should download correctly(md5 ok) with get_file" do
74
+ tmpfile = "/tmp/picture"
75
+ response = @session.get_file "/picture", tmpfile
76
+ response.body.should be_nil
77
+ File.size(File.join(File.dirname(__FILE__),"../pic.png")).should == File.size(tmpfile)
78
+ FileUtils.rm tmpfile
79
+ end
80
+
68
81
  it "should include custom headers in a request" do
69
82
  response = @session.get("/test", {"User-Agent" => "PatronTest"})
70
83
  body = YAML::load(response.body)
71
84
  body.header["user-agent"].should == ["PatronTest"]
72
85
  end
73
86
 
87
+ it "should include default headers in a request, if they were defined" do
88
+ @session.headers = {"User-Agent" => "PatronTest"}
89
+ response = @session.get("/test")
90
+ body = YAML::load(response.body)
91
+ body.header["user-agent"].should == ["PatronTest"]
92
+ end
93
+
74
94
  it "should merge custom headers with session headers" do
75
95
  @session.headers["X-Test"] = "Testing"
76
96
  response = @session.get("/test", {"User-Agent" => "PatronTest"})
@@ -146,6 +166,14 @@ describe Patron::Session do
146
166
  body.header['content-length'].should == [data.size.to_s]
147
167
  end
148
168
 
169
+ it "should upload data with :delete" do
170
+ data = "upload data"
171
+ response = @session.request(:delete, "/test", {}, :data => data)
172
+ body = YAML::load(response.body)
173
+ body.request_method.should == "DELETE"
174
+ body.header['content-length'].should == [data.size.to_s]
175
+ end
176
+
149
177
  it "should raise when no data is provided to :put" do
150
178
  lambda { @session.put("/test", nil) }.should raise_error(ArgumentError)
151
179
  end
@@ -0,0 +1,284 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
4
+ ##
5
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ ## of this software and associated documentation files (the "Software"), to deal
7
+ ## in the Software without restriction, including without limitation the rights
8
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ ## copies of the Software, and to permit persons to whom the Software is
10
+ ## furnished to do so, subject to the following conditions:
11
+ ##
12
+ ## The above copyright notice and this permission notice shall be included in
13
+ ## all copies or substantial portions of the Software.
14
+ ##
15
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ ## THE SOFTWARE.
22
+ ##
23
+ ## -------------------------------------------------------------------
24
+ require File.expand_path("./spec") + '/spec_helper.rb'
25
+ require 'webrick'
26
+ require 'yaml'
27
+ require 'base64'
28
+ require 'fileutils'
29
+
30
+ describe Patron::Session do
31
+
32
+ before(:each) do
33
+ @session = Patron::Session.new
34
+ @session.base_url = "https://localhost:9043"
35
+ @session.insecure = true
36
+ end
37
+
38
+ it "should retrieve a url with :get" do
39
+ response = @session.get("/test")
40
+ body = YAML::load(response.body)
41
+ body.request_method.should == "GET"
42
+ end
43
+
44
+ it "should download content with :get and a file path" do
45
+ tmpfile = "/tmp/patron_test.yaml"
46
+ response = @session.get_file "/test", tmpfile
47
+ response.body.should be_nil
48
+ body = YAML::load_file(tmpfile)
49
+ body.request_method.should == "GET"
50
+ FileUtils.rm tmpfile
51
+ end
52
+
53
+ it "should download correctly(md5 ok) with get_file" do
54
+ tmpfile = "/tmp/picture"
55
+ response = @session.get_file "/picture", tmpfile
56
+ response.body.should be_nil
57
+ File.size(File.join(File.dirname(__FILE__),"../pic.png")).should == File.size(tmpfile)
58
+ FileUtils.rm tmpfile
59
+ end
60
+
61
+ it "should include custom headers in a request" do
62
+ response = @session.get("/test", {"User-Agent" => "PatronTest"})
63
+ body = YAML::load(response.body)
64
+ body.header["user-agent"].should == ["PatronTest"]
65
+ end
66
+
67
+ it "should merge custom headers with session headers" do
68
+ @session.headers["X-Test"] = "Testing"
69
+ response = @session.get("/test", {"User-Agent" => "PatronTest"})
70
+ body = YAML::load(response.body)
71
+ body.header["user-agent"].should == ["PatronTest"]
72
+ body.header["x-test"].should == ["Testing"]
73
+ end
74
+
75
+ it "should raise an exception on timeout" do
76
+ @session.timeout = 1
77
+ lambda {@session.get("/timeout")}.should raise_error(Patron::TimeoutError)
78
+ end
79
+
80
+ it "should follow redirects by default" do
81
+ @session.max_redirects = 1
82
+ response = @session.get("/redirect")
83
+ body = YAML::load(response.body)
84
+ response.status.should == 200
85
+ body.path.should == "/test"
86
+ end
87
+
88
+ it "should include redirect count in response" do
89
+ @session.max_redirects = 1
90
+ response = @session.get("/redirect")
91
+ response.redirect_count.should == 1
92
+ end
93
+
94
+ it "should not follow redirects when configured to do so" do
95
+ @session.max_redirects = 0
96
+ response = @session.get("/redirect")
97
+ response.status.should == 301
98
+ response.body.should be_empty
99
+ end
100
+
101
+ it "should retrieve URL metadata with :head" do
102
+ response = @session.head("/test")
103
+ response.status.should == 200
104
+ response.body.should be_empty
105
+ response.headers.should_not be_empty
106
+ end
107
+
108
+ it "should send a delete request with :delete" do
109
+ response = @session.delete("/test")
110
+ body = YAML::load(response.body)
111
+ body.request_method.should == "DELETE"
112
+ end
113
+
114
+ it "should send a COPY request with :copy" do
115
+ response = @session.copy("/test", "/test2")
116
+ body = YAML::load(response.body)
117
+ body.request_method.should == "COPY"
118
+ end
119
+
120
+ it "should include a Destination header in COPY requests" do
121
+ response = @session.copy("/test", "/test2")
122
+ body = YAML::load(response.body)
123
+ body.header['destination'].first.should == "/test2"
124
+ end
125
+
126
+ it "should upload data with :get" do
127
+ data = "upload data"
128
+ response = @session.request(:get, "/test", {}, :data => data)
129
+ body = YAML::load(response.body)
130
+ body.request_method.should == "GET"
131
+ body.header['content-length'].should == [data.size.to_s]
132
+ end
133
+
134
+ it "should upload data with :put" do
135
+ data = "upload data"
136
+ response = @session.put("/test", data)
137
+ body = YAML::load(response.body)
138
+ body.request_method.should == "PUT"
139
+ body.header['content-length'].should == [data.size.to_s]
140
+ end
141
+
142
+ it "should raise when no data is provided to :put" do
143
+ lambda { @session.put("/test", nil) }.should raise_error(ArgumentError)
144
+ end
145
+
146
+ it "should upload a file with :put" do
147
+ response = @session.put_file("/test", "LICENSE")
148
+ body = YAML::load(response.body)
149
+ body.request_method.should == "PUT"
150
+ end
151
+
152
+ it "should raise when no file is provided to :put" do
153
+ lambda { @session.put_file("/test", nil) }.should raise_error(ArgumentError)
154
+ end
155
+
156
+ it "should use chunked encoding when uploading a file with :put" do
157
+ response = @session.put_file("/test", "LICENSE")
158
+ body = YAML::load(response.body)
159
+ body.header['transfer-encoding'].first.should == "chunked"
160
+ end
161
+
162
+ it "should upload data with :post" do
163
+ data = "upload data"
164
+ response = @session.post("/test", data)
165
+ body = YAML::load(response.body)
166
+ body.request_method.should == "POST"
167
+ body.header['content-length'].should == [data.size.to_s]
168
+ end
169
+
170
+ it "should post a hash of arguments as a urlencoded form" do
171
+ data = {:foo => 123, 'baz' => '++hello world++'}
172
+ response = @session.post("/testpost", data)
173
+ body = YAML::load(response.body)
174
+ body['content_type'].should == "application/x-www-form-urlencoded"
175
+ body['body'].should match(/baz=%2B%2Bhello%20world%2B%2B/)
176
+ body['body'].should match(/foo=123/)
177
+ end
178
+
179
+ it "should raise when no data is provided to :post" do
180
+ lambda { @session.post("/test", nil) }.should raise_error(ArgumentError)
181
+ end
182
+
183
+ it "should upload a file with :post" do
184
+ response = @session.post_file("/test", "LICENSE")
185
+ body = YAML::load(response.body)
186
+ body.request_method.should == "POST"
187
+ end
188
+
189
+ it "should upload a multipart with :post" do
190
+ response = @session.post_multipart("/test", { :test_data => "123" }, { :test_file => "LICENSE" } )
191
+ body = YAML::load(response.body)
192
+ body.request_method.should == "POST"
193
+ end
194
+
195
+ it "should raise when no file is provided to :post" do
196
+ lambda { @session.post_file("/test", nil) }.should raise_error(ArgumentError)
197
+ end
198
+
199
+ it "should use chunked encoding when uploading a file with :post" do
200
+ response = @session.post_file("/test", "LICENSE")
201
+ body = YAML::load(response.body)
202
+ body.header['transfer-encoding'].first.should == "chunked"
203
+ end
204
+
205
+ it "should handle cookies if set" do
206
+ @session.handle_cookies
207
+ response = @session.get("/setcookie").body
208
+ YAML::load(response).header['cookie'].first.should == "session_id=foo123"
209
+ end
210
+
211
+ it "should not handle cookies by default" do
212
+ response = @session.get("/setcookie").body
213
+ YAML::load(response).header.should_not include('cookie')
214
+ end
215
+
216
+ it "should ignore a wrong Content-Length when asked to" do
217
+ lambda {
218
+ @session.ignore_content_length = true
219
+ @session.get("/wrongcontentlength")
220
+ }.should_not raise_error
221
+ end
222
+
223
+ it "should fail by default with a Content-Length too high" do
224
+ lambda {
225
+ @session.ignore_content_length = nil
226
+ @session.get("/wrongcontentlength")
227
+ }.should raise_error(Patron::PartialFileError)
228
+ end
229
+
230
+ it "should raise exception if cookie store is not writable or readable" do
231
+ lambda { @session.handle_cookies("/trash/clash/foo") }.should raise_error(ArgumentError)
232
+ end
233
+
234
+ it "should work with multiple threads" do
235
+ threads = []
236
+ 3.times do
237
+ threads << Thread.new do
238
+ session = Patron::Session.new
239
+ session.base_url = "https://localhost:9043"
240
+ session.insecure = true
241
+ session.post_file("/test", "LICENSE")
242
+ end
243
+ end
244
+ threads.each {|t| t.join }
245
+ end
246
+
247
+ xit "should fail when insecure mode is off" do
248
+ # This spec fails, but I suspect that it is a setup problem.
249
+ lambda {
250
+ @session.insecure = nil
251
+ response = @session.get("/test")
252
+ }.should raise_error(Patron::Error)
253
+ end
254
+
255
+ it "should work when insecure mode is off but certificate is supplied" do
256
+ @session.insecure = nil
257
+ @session.cacert = 'spec/certs/cacert.pem'
258
+ response = @session.get("/test")
259
+ body = YAML::load(response.body)
260
+ body.request_method.should == "GET"
261
+ end
262
+
263
+ it "should work with different SSL versions" do
264
+ ['SSLv3', 'TLSv1'].each do |version|
265
+ @session.ssl_version = version
266
+ response = @session.get("/test")
267
+ response.status.should == 200
268
+ end
269
+ end
270
+
271
+ # ------------------------------------------------------------------------
272
+ describe 'when debug is enabled' do
273
+ it 'it should not clobber stderr' do
274
+ rdev = STDERR.stat.rdev
275
+
276
+ @session.enable_debug
277
+ STDERR.stat.rdev.should be == rdev
278
+
279
+ @session.enable_debug
280
+ STDERR.stat.rdev.should be == rdev
281
+ end
282
+ end
283
+
284
+ end
data/spec/spec_helper.rb CHANGED
@@ -29,4 +29,5 @@ require 'patron'
29
29
 
30
30
  Dir['./spec/support/**/*.rb'].each { |fn| require fn }
31
31
 
32
- PatronTestServer.start if RUBY_VERSION >= '1.9'
32
+ PatronTestServer.start(nil, false, 9001) if RUBY_VERSION >= '1.9'
33
+ PatronTestServer.start(nil, true, 9043) if RUBY_VERSION >= '1.9'
@@ -24,6 +24,9 @@
24
24
  ## -------------------------------------------------------------------
25
25
  require 'yaml'
26
26
  require 'webrick'
27
+ require 'webrick/https'
28
+ require 'openssl'
29
+
27
30
  include WEBrick
28
31
 
29
32
  # This ugly little hack is necessary to make the specs pass when running
@@ -125,22 +128,32 @@ end
125
128
 
126
129
  class PatronTestServer
127
130
 
128
- def self.start( log_file = nil )
129
- new(log_file).start
131
+ def self.start( log_file = nil, ssl = false, port = 9001 )
132
+ new(log_file, ssl, port).start
130
133
  end
131
134
 
132
- def initialize( log_file = nil )
135
+ def initialize( log_file = nil, ssl = false, port = 9001 )
133
136
  log_file ||= StringIO.new
134
137
  log = WEBrick::Log.new(log_file)
135
138
 
136
- @server = WEBrick::HTTPServer.new(
137
- :Port => 9001,
139
+ options = {
140
+ :Port => port,
138
141
  :Logger => log,
139
142
  :AccessLog => [
140
143
  [ log, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
141
144
  [ log, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
142
145
  ]
143
- )
146
+ }
147
+
148
+ if ssl
149
+ options[:SSLEnable] = true
150
+ options[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.open("spec/certs/cacert.pem").read)
151
+ options[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open("spec/certs/privkey.pem").read)
152
+ options[:SSLCertName] = [ ["CN", WEBrick::Utils::getservername ] ]
153
+ end
154
+
155
+ @server = WEBrick::HTTPServer.new(options)
156
+
144
157
  @server.mount("/test", TestServlet)
145
158
  @server.mount("/testpost", TestPostBodyServlet)
146
159
  @server.mount("/timeout", TimeoutServlet)
@@ -149,6 +162,7 @@ class PatronTestServer
149
162
  @server.mount("/setcookie", SetCookieServlet)
150
163
  @server.mount("/repetitiveheader", RepetitiveHeaderServlet)
151
164
  @server.mount("/wrongcontentlength", WrongContentLengthServlet)
165
+
152
166
  end
153
167
 
154
168
  def start
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.18
4
+ version: 0.4.20
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-05 00:00:00.000000000 Z
12
+ date: 2015-02-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &70336820705120 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 1.0.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70336820705120
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake-compiler
27
- requirement: &70336820704660 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: 0.7.5
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70336820704660
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.7.5
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rspec
38
- requirement: &70336820704200 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: 2.3.0
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70336820704200
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.0
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rcov
49
- requirement: &70336820703740 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,12 @@ dependencies:
54
69
  version: 0.9.9
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70336820703740
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.9
58
78
  description: Ruby HTTP client library based on libcurl
59
79
  email:
60
80
  - phil.toland@gmail.com
@@ -69,7 +89,7 @@ files:
69
89
  - Gemfile
70
90
  - Gemfile.lock
71
91
  - LICENSE
72
- - README.txt
92
+ - README.md
73
93
  - Rakefile
74
94
  - ext/patron/.gitignore
75
95
  - ext/patron/extconf.rb
@@ -89,10 +109,13 @@ files:
89
109
  - pic.png
90
110
  - script/console
91
111
  - script/test_server
112
+ - spec/certs/cacert.pem
113
+ - spec/certs/privkey.pem
92
114
  - spec/patron_spec.rb
93
115
  - spec/request_spec.rb
94
116
  - spec/response_spec.rb
95
117
  - spec/session_spec.rb
118
+ - spec/session_ssl_spec.rb
96
119
  - spec/spec_helper.rb
97
120
  - spec/support/test_server.rb
98
121
  - spec/util_spec.rb
@@ -117,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
140
  version: 1.2.0
118
141
  requirements: []
119
142
  rubyforge_project: patron
120
- rubygems_version: 1.8.10
143
+ rubygems_version: 1.8.23
121
144
  signing_key:
122
145
  specification_version: 3
123
146
  summary: Patron HTTP Client