patron 0.6.1 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/ext/patron/session_ext.c +48 -57
- data/lib/patron/request.rb +1 -1
- data/lib/patron/session.rb +12 -0
- data/lib/patron/version.rb +1 -1
- data/spec/session_spec.rb +21 -2
- data/spec/support/test_server.rb +8 -1
- 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: c363a7f520fb90344efb2251b25a0dbbc6e0d5db
|
4
|
+
data.tar.gz: f95d681849dd57101b33408327fc3aa38d0dc2e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1945f68df49b6f96ee53166382807ac5e5a19bd00d2746e325d3af02ffe54b14db6f5ad92a55fe6322f5183b25b047cd2879503b6dfbb5bc9c1afc69c5c617ee
|
7
|
+
data.tar.gz: a487793a4bb938d77804e4f0ea083c61afad062014cacbadcb40343f31ddb3fb55889f844f7b0610101f06f1a765f3c53fe1257bf9b48cabe4fda2ae71398334
|
data/Gemfile.lock
CHANGED
data/ext/patron/session_ext.c
CHANGED
@@ -77,19 +77,6 @@ static size_t session_write_handler(char* stream, size_t size, size_t nmemb, mem
|
|
77
77
|
return size * nmemb;
|
78
78
|
}
|
79
79
|
|
80
|
-
static size_t session_read_handler(char* stream, size_t size, size_t nmemb, char **buffer) {
|
81
|
-
size_t result = 0;
|
82
|
-
|
83
|
-
if (buffer != NULL && *buffer != NULL) {
|
84
|
-
size_t len = size * nmemb;
|
85
|
-
char *s1 = strncpy(stream, *buffer, len);
|
86
|
-
result = strlen(s1);
|
87
|
-
*buffer += result;
|
88
|
-
}
|
89
|
-
|
90
|
-
return result;
|
91
|
-
}
|
92
|
-
|
93
80
|
/* A non-zero return value from the progress handler will terminate the current
|
94
81
|
* request. We use this fact in order to interrupt any request when either the
|
95
82
|
* user calls the "interrupt" method on the session or when the Ruby interpreter
|
@@ -319,6 +306,16 @@ static int formadd_files(VALUE data_key, VALUE data_value, VALUE self) {
|
|
319
306
|
return 0;
|
320
307
|
}
|
321
308
|
|
309
|
+
// Set the given char pointer and it's length to be the CURL request body
|
310
|
+
static void set_curl_request_body(CURL* curl, char* buf, curl_off_t len) {
|
311
|
+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
|
312
|
+
#ifdef CURLOPT_POSTFIELDSIZE_LARGE
|
313
|
+
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, len);
|
314
|
+
#else
|
315
|
+
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
|
316
|
+
#endif
|
317
|
+
}
|
318
|
+
|
322
319
|
static void set_chunked_encoding(struct curl_state *state) {
|
323
320
|
state->headers = curl_slist_append(state->headers, "Transfer-Encoding: chunked");
|
324
321
|
}
|
@@ -353,10 +350,10 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
353
350
|
VALUE cacert = Qnil;
|
354
351
|
VALUE ssl_version = Qnil;
|
355
352
|
VALUE buffer_size = Qnil;
|
356
|
-
VALUE action_name =
|
357
|
-
VALUE a_c_encoding =
|
353
|
+
VALUE action_name = rb_funcall(request, rb_intern("action"), 0);
|
354
|
+
VALUE a_c_encoding = rb_funcall(request, rb_intern("automatic_content_encoding"), 0);
|
358
355
|
|
359
|
-
headers =
|
356
|
+
headers = rb_funcall(request, rb_intern("headers"), 0);
|
360
357
|
if (!NIL_P(headers)) {
|
361
358
|
if (rb_type(headers) != T_HASH) {
|
362
359
|
rb_raise(rb_eArgError, "Headers must be passed in a hash.");
|
@@ -366,23 +363,20 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
366
363
|
}
|
367
364
|
|
368
365
|
action = SYM2ID(action_name);
|
369
|
-
if(
|
366
|
+
if(rb_funcall(request, rb_intern("force_ipv4"), 0)) {
|
370
367
|
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
371
368
|
}
|
372
369
|
if (action == rb_intern("get")) {
|
373
|
-
VALUE data =
|
374
|
-
VALUE download_file =
|
370
|
+
VALUE data = rb_funcall(request, rb_intern("upload_data"), 0);
|
371
|
+
VALUE download_file = rb_funcall(request, rb_intern("file_name"), 0);
|
375
372
|
|
376
373
|
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
377
374
|
if (!NIL_P(data)) {
|
378
375
|
data = rb_funcall(data, rb_intern("to_s"), 0);
|
379
376
|
long len = RSTRING_LEN(data);
|
380
377
|
state->upload_buf = StringValuePtr(data);
|
381
|
-
|
378
|
+
set_curl_request_body(curl, state->upload_buf, len);
|
382
379
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
|
383
|
-
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &session_read_handler);
|
384
|
-
curl_easy_setopt(curl, CURLOPT_READDATA, &state->upload_buf);
|
385
|
-
curl_easy_setopt(curl, CURLOPT_INFILESIZE, len);
|
386
380
|
}
|
387
381
|
if (!NIL_P(download_file)) {
|
388
382
|
state->download_file = open_file(download_file, "wb");
|
@@ -390,35 +384,32 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
390
384
|
} else {
|
391
385
|
state->download_file = NULL;
|
392
386
|
}
|
393
|
-
} else if (action == rb_intern("post") || action == rb_intern("put")) {
|
394
|
-
VALUE data =
|
395
|
-
VALUE filename =
|
396
|
-
VALUE multipart =
|
397
|
-
|
387
|
+
} else if (action == rb_intern("post") || action == rb_intern("put") || action == rb_intern("patch")) {
|
388
|
+
VALUE data = rb_funcall(request, rb_intern("upload_data"), 0);
|
389
|
+
VALUE filename = rb_funcall(request, rb_intern("file_name"), 0);
|
390
|
+
VALUE multipart = rb_funcall(request, rb_intern("multipart"), 0);
|
391
|
+
|
392
|
+
if (action == rb_intern("post")) {
|
393
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
|
394
|
+
} else if (action == rb_intern("put")) {
|
395
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
396
|
+
} else if (action == rb_intern("patch")) {
|
397
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
398
|
+
}
|
399
|
+
|
398
400
|
if (!NIL_P(data) && NIL_P(multipart)) {
|
399
401
|
data = rb_funcall(data, rb_intern("to_s"), 0);
|
400
|
-
long len = RSTRING_LEN(data);
|
401
|
-
state->upload_buf = StringValuePtr(data);
|
402
|
-
|
403
402
|
if (action == rb_intern("post")) {
|
404
403
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
405
|
-
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, state->upload_buf);
|
406
|
-
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
|
407
|
-
} else {
|
408
|
-
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
409
|
-
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &session_read_handler);
|
410
|
-
curl_easy_setopt(curl, CURLOPT_READDATA, &state->upload_buf);
|
411
|
-
curl_easy_setopt(curl, CURLOPT_INFILESIZE, len);
|
412
404
|
}
|
405
|
+
long len = RSTRING_LEN(data);
|
406
|
+
state->upload_buf = StringValuePtr(data);
|
407
|
+
set_curl_request_body(curl, state->upload_buf, len);
|
413
408
|
} else if (!NIL_P(filename) && NIL_P(multipart)) {
|
414
409
|
set_chunked_encoding(state);
|
415
410
|
|
416
411
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
417
412
|
|
418
|
-
if (action == rb_intern("post")) {
|
419
|
-
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
|
420
|
-
}
|
421
|
-
|
422
413
|
state->upload_file = open_file(filename, "rb");
|
423
414
|
curl_easy_setopt(curl, CURLOPT_READDATA, state->upload_file);
|
424
415
|
} else if (!NIL_P(multipart)) {
|
@@ -441,8 +432,7 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
441
432
|
|
442
433
|
// support for data passed with a DELETE request (e.g.: used by elasticsearch)
|
443
434
|
} else if (action == rb_intern("delete")) {
|
444
|
-
VALUE data =
|
445
|
-
|
435
|
+
VALUE data = rb_funcall(request, rb_intern("upload_data"), 0);
|
446
436
|
if (!NIL_P(data)) {
|
447
437
|
long len = RSTRING_LEN(data);
|
448
438
|
state->upload_buf = StringValuePtr(data);
|
@@ -475,57 +465,58 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
475
465
|
#endif
|
476
466
|
}
|
477
467
|
|
478
|
-
url =
|
468
|
+
url = rb_funcall(request, rb_intern("url"), 0);
|
479
469
|
if (NIL_P(url)) {
|
480
470
|
rb_raise(rb_eArgError, "Must provide a URL");
|
481
471
|
}
|
482
472
|
curl_easy_setopt(curl, CURLOPT_URL, StringValuePtr(url));
|
483
473
|
|
484
|
-
timeout =
|
474
|
+
timeout = rb_funcall(request, rb_intern("timeout"), 0);
|
485
475
|
if (!NIL_P(timeout)) {
|
486
476
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, FIX2INT(timeout));
|
487
477
|
}
|
488
478
|
|
489
|
-
timeout =
|
479
|
+
timeout = rb_funcall(request, rb_intern("connect_timeout"), 0);
|
490
480
|
if (!NIL_P(timeout)) {
|
491
481
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FIX2INT(timeout));
|
492
482
|
}
|
493
483
|
|
494
|
-
redirects =
|
484
|
+
redirects = rb_funcall(request, rb_intern("max_redirects"), 0);
|
495
485
|
if (!NIL_P(redirects)) {
|
496
486
|
int r = FIX2INT(redirects);
|
497
487
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, r == 0 ? 0 : 1);
|
498
488
|
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, r);
|
499
489
|
}
|
500
490
|
|
501
|
-
proxy =
|
491
|
+
proxy = rb_funcall(request, rb_intern("proxy"), 0);
|
502
492
|
if (!NIL_P(proxy)) {
|
503
493
|
curl_easy_setopt(curl, CURLOPT_PROXY, StringValuePtr(proxy));
|
504
494
|
}
|
505
495
|
|
506
|
-
proxy_type =
|
496
|
+
proxy_type = rb_funcall(request, rb_intern("proxy_type"), 0);
|
507
497
|
if (!NIL_P(proxy_type)) {
|
508
498
|
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, NUM2LONG(proxy_type));
|
509
499
|
}
|
510
500
|
|
511
501
|
credentials = rb_funcall(request, rb_intern("credentials"), 0);
|
512
502
|
if (!NIL_P(credentials)) {
|
513
|
-
|
503
|
+
VALUE auth_type = rb_funcall(request, rb_intern("auth_type"), 0);
|
504
|
+
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, NUM2LONG(auth_type));
|
514
505
|
curl_easy_setopt(curl, CURLOPT_USERPWD, StringValuePtr(credentials));
|
515
506
|
}
|
516
507
|
|
517
|
-
ignore_content_length =
|
508
|
+
ignore_content_length = rb_funcall(request, rb_intern("ignore_content_length"), 0);
|
518
509
|
if (!NIL_P(ignore_content_length)) {
|
519
510
|
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1);
|
520
511
|
}
|
521
512
|
|
522
|
-
insecure =
|
513
|
+
insecure = rb_funcall(request, rb_intern("insecure"), 0);
|
523
514
|
if(!NIL_P(insecure)) {
|
524
515
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
525
516
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
526
517
|
}
|
527
518
|
|
528
|
-
ssl_version =
|
519
|
+
ssl_version = rb_funcall(request, rb_intern("ssl_version"), 0);
|
529
520
|
if(!NIL_P(ssl_version)) {
|
530
521
|
VALUE ssl_version_str = rb_funcall(ssl_version, rb_intern("to_s"), 0);
|
531
522
|
char* version = StringValuePtr(ssl_version_str);
|
@@ -540,12 +531,12 @@ static void set_options_from_request(VALUE self, VALUE request) {
|
|
540
531
|
}
|
541
532
|
}
|
542
533
|
|
543
|
-
cacert =
|
534
|
+
cacert = rb_funcall(request, rb_intern("cacert"), 0);
|
544
535
|
if(!NIL_P(cacert)) {
|
545
536
|
curl_easy_setopt(curl, CURLOPT_CAINFO, StringValuePtr(cacert));
|
546
537
|
}
|
547
538
|
|
548
|
-
buffer_size =
|
539
|
+
buffer_size = rb_funcall(request, rb_intern("buffer_size"), 0);
|
549
540
|
if (!NIL_P(buffer_size)) {
|
550
541
|
curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, NUM2LONG(buffer_size));
|
551
542
|
}
|
@@ -575,7 +566,7 @@ static VALUE create_response(VALUE self, CURL* curl, VALUE header_buffer, VALUE
|
|
575
566
|
|
576
567
|
args[3] = header_buffer;
|
577
568
|
args[4] = body_buffer;
|
578
|
-
args[5] =
|
569
|
+
args[5] = rb_funcall(self, rb_intern("default_response_charset"), 0);
|
579
570
|
|
580
571
|
responseKlass = rb_funcall(self, rb_intern("response_class"), 0);
|
581
572
|
return rb_class_new_instance(6, args, responseKlass);
|
data/lib/patron/request.rb
CHANGED
@@ -34,7 +34,7 @@ module Patron
|
|
34
34
|
class Request
|
35
35
|
|
36
36
|
# Contains the valid HTTP verbs that can be used to perform requests
|
37
|
-
VALID_ACTIONS = %w[GET PUT POST DELETE HEAD COPY]
|
37
|
+
VALID_ACTIONS = %w[GET PUT POST DELETE HEAD COPY PATCH]
|
38
38
|
|
39
39
|
# Initializes a new Request, which defaults to the GET HTTP verb and
|
40
40
|
# has it's timeouts set to 0
|
data/lib/patron/session.rb
CHANGED
@@ -232,6 +232,18 @@ module Patron
|
|
232
232
|
request(:put, url, headers, :data => data)
|
233
233
|
end
|
234
234
|
|
235
|
+
# Uploads the passed `data` to the specified `url` using an HTTP PATCH. Note that
|
236
|
+
# unline ++post++, a Hash is not accepted as the ++data++ argument.
|
237
|
+
#
|
238
|
+
# @todo inconsistency with "post" - Hash not accepted
|
239
|
+
# @param url[String] the URL to fetch
|
240
|
+
# @param data[#to_s] an object that can be converted to a String to create the request body
|
241
|
+
# @param headers[Hash] the hash of header keys to values
|
242
|
+
# @return [Patron::Response]
|
243
|
+
def patch(url, data, headers = {})
|
244
|
+
request(:patch, url, headers, :data => data)
|
245
|
+
end
|
246
|
+
|
235
247
|
# Uploads the contents of `file` to the specified `url` using an HTTP PUT. The file will be
|
236
248
|
# sent "as-is" without any multipart encoding.
|
237
249
|
#
|
data/lib/patron/version.rb
CHANGED
data/spec/session_spec.rb
CHANGED
@@ -194,14 +194,33 @@ describe Patron::Session do
|
|
194
194
|
expect(body.request_method).to be == "GET"
|
195
195
|
end
|
196
196
|
|
197
|
+
it "should upload data with :get" do
|
198
|
+
# Sending a request body with a GET request is a technique seldom used,
|
199
|
+
# but it does get used nevertheless - for instance, it is a usual
|
200
|
+
# practice when interacting with an ElasticSearch cluster where
|
201
|
+
# you can have very deeply going queries, which are still technically GETs
|
202
|
+
data = SecureRandom.random_bytes(1024 * 24)
|
203
|
+
response = @session.request(:get, "/test", {}, :data => data)
|
204
|
+
body = YAML::load(response.body)
|
205
|
+
expect(body.request_method).to be == "GET"
|
206
|
+
expect(body.header['content-length']).to be == [data.size.to_s]
|
207
|
+
end
|
208
|
+
|
197
209
|
it "should upload data with :put" do
|
198
|
-
data =
|
210
|
+
data = SecureRandom.random_bytes(1024 * 24)
|
199
211
|
response = @session.put("/test", data)
|
200
212
|
body = YAML::load(response.body)
|
201
213
|
expect(body.request_method).to be == "PUT"
|
202
214
|
expect(body.header['content-length']).to be == [data.size.to_s]
|
203
215
|
end
|
204
216
|
|
217
|
+
it "should upload data with :patch" do
|
218
|
+
data = "upload data"
|
219
|
+
response = @session.patch("/testpatch", data)
|
220
|
+
body = YAML::load(response.body)
|
221
|
+
expect(body["body"]).to eq("upload data")
|
222
|
+
end
|
223
|
+
|
205
224
|
it "should upload data with :delete" do
|
206
225
|
data = "upload data"
|
207
226
|
response = @session.request(:delete, "/test", {}, :data => data)
|
@@ -245,7 +264,7 @@ describe Patron::Session do
|
|
245
264
|
expect(body.header['content-length']).to be == [data.size.to_s]
|
246
265
|
end
|
247
266
|
|
248
|
-
it "should
|
267
|
+
it "should POST a hash of arguments as a urlencoded form" do
|
249
268
|
data = {:foo => 123, 'baz' => '++hello world++'}
|
250
269
|
response = @session.post("/testpost", data)
|
251
270
|
body = YAML::load(response.body)
|
data/spec/support/test_server.rb
CHANGED
@@ -115,6 +115,13 @@ class TestPostBodyServlet < HTTPServlet::AbstractServlet
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
class TestPatchBodyServlet < HTTPServlet::AbstractServlet
|
119
|
+
include RespondWith
|
120
|
+
def do_PATCH(req, res)
|
121
|
+
respond_with(:PATCH, {'body' => req.body, 'content_type' => req.content_type}, res)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
118
125
|
class SetCookieServlet < HTTPServlet::AbstractServlet
|
119
126
|
def do_GET(req, res)
|
120
127
|
res['Set-Cookie'] = "session_id=foo123"
|
@@ -178,6 +185,7 @@ class PatronTestServer
|
|
178
185
|
|
179
186
|
@server.mount("/test", TestServlet)
|
180
187
|
@server.mount("/testpost", TestPostBodyServlet)
|
188
|
+
@server.mount("/testpatch", TestPatchBodyServlet)
|
181
189
|
@server.mount("/timeout", TimeoutServlet)
|
182
190
|
@server.mount("/redirect", RedirectServlet)
|
183
191
|
@server.mount("/picture", PictureServlet)
|
@@ -185,7 +193,6 @@ class PatronTestServer
|
|
185
193
|
@server.mount("/repetitiveheader", RepetitiveHeaderServlet)
|
186
194
|
@server.mount("/wrongcontentlength", WrongContentLengthServlet)
|
187
195
|
@server.mount("/gzip-compressed", GzipServlet)
|
188
|
-
|
189
196
|
end
|
190
197
|
|
191
198
|
def start
|
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.6.
|
4
|
+
version: 0.6.3
|
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-04-
|
11
|
+
date: 2016-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|