httparty 0.16.4 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +23 -0
- data/.rubocop_todo.yml +1 -1
- data/Changelog.md +55 -0
- data/Gemfile +5 -0
- data/README.md +4 -4
- data/docs/README.md +70 -5
- data/examples/README.md +6 -0
- data/examples/aaws.rb +6 -2
- data/examples/idn.rb +10 -0
- data/examples/peer_cert.rb +9 -0
- data/httparty.gemspec +1 -2
- data/lib/httparty/connection_adapter.rb +41 -10
- data/lib/httparty/cookie_hash.rb +10 -8
- data/lib/httparty/decompressor.rb +92 -0
- data/lib/httparty/exceptions.rb +3 -1
- data/lib/httparty/hash_conversions.rb +4 -2
- data/lib/httparty/headers_processor.rb +32 -0
- data/lib/httparty/logger/apache_formatter.rb +4 -2
- data/lib/httparty/logger/curl_formatter.rb +6 -4
- data/lib/httparty/logger/logger.rb +2 -0
- data/lib/httparty/logger/logstash_formatter.rb +4 -2
- data/lib/httparty/module_inheritable_attributes.rb +3 -1
- data/lib/httparty/net_digest_auth.rb +9 -10
- data/lib/httparty/parser.rb +9 -5
- data/lib/httparty/request/body.rb +24 -10
- data/lib/httparty/request/multipart_boundary.rb +2 -0
- data/lib/httparty/request.rb +67 -96
- data/lib/httparty/response/headers.rb +2 -0
- data/lib/httparty/response.rb +24 -4
- data/lib/httparty/{fragment_with_response.rb → response_fragment.rb} +6 -5
- data/lib/httparty/text_encoder.rb +72 -0
- data/lib/httparty/utils.rb +2 -0
- data/lib/httparty/version.rb +3 -1
- data/lib/httparty.rb +58 -35
- metadata +12 -108
- data/.travis.yml +0 -11
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -56
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -92
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/example.html +0 -10
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
- data/spec/fixtures/ssl/generated/ca.crt +0 -16
- data/spec/fixtures/ssl/generated/ca.key +0 -15
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
- data/spec/fixtures/ssl/generated/server.crt +0 -13
- data/spec/fixtures/ssl/generated/server.key +0 -15
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/tiny.gif +0 -0
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -502
- data/spec/httparty/cookie_hash_spec.rb +0 -100
- data/spec/httparty/exception_spec.rb +0 -45
- data/spec/httparty/fragment_with_response_spec.rb +0 -14
- data/spec/httparty/hash_conversions_spec.rb +0 -58
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -40
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
- data/spec/httparty/logger/logger_spec.rb +0 -43
- data/spec/httparty/logger/logstash_formatter_spec.rb +0 -44
- data/spec/httparty/net_digest_auth_spec.rb +0 -270
- data/spec/httparty/parser_spec.rb +0 -190
- data/spec/httparty/request/body_spec.rb +0 -165
- data/spec/httparty/request_spec.rb +0 -1367
- data/spec/httparty/response_spec.rb +0 -368
- data/spec/httparty/ssl_spec.rb +0 -74
- data/spec/httparty_spec.rb +0 -923
- data/spec/spec_helper.rb +0 -56
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bde34a85d8b010341759c1b2b42dfe58cad693c39f047b9803ac90afbc13290b
|
4
|
+
data.tar.gz: b5248420c90ea545dfa9e6e234d6c597b4c7306dfc8d58ff94dca82e405e0ed1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13316910a85a75d1204c64be41e995475b26abf9aad1165c06349c296d0b3f0f6ae644b00d8bcf14adc3d9a11659bffd060a5101dc88718af74d0324adde9e30
|
7
|
+
data.tar.gz: 668fac0ca6a513e64dead9b633ecb12c4ff926cb017e4e7e244249cfb361f93e1aa515ef3fb6b80e6245264e7da38d0599abec9931c5b33b88d7235b966b0aa1
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: CI
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
strategy:
|
7
|
+
matrix:
|
8
|
+
ruby:
|
9
|
+
- 2.3
|
10
|
+
- 2.4
|
11
|
+
- 2.5
|
12
|
+
- 2.6
|
13
|
+
- 2.7
|
14
|
+
steps:
|
15
|
+
- name: Check out repository code
|
16
|
+
uses: actions/checkout@v2
|
17
|
+
- name: Set up Ruby
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: ${{ matrix.ruby }}
|
21
|
+
bundler-cache: true # Run "bundle install", and cache the result automatically.
|
22
|
+
- name: Run Rake
|
23
|
+
run: bundle exec rake
|
data/.rubocop_todo.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,3 +1,58 @@
|
|
1
|
+
## 0.20.0
|
2
|
+
|
3
|
+
Breaking changes
|
4
|
+
|
5
|
+
* Require Ruby >= 2.3.0
|
6
|
+
|
7
|
+
Fixes
|
8
|
+
|
9
|
+
* [`Marshal.dump` fails on response objects when request option `:logger` is set or `:parser` is a proc](https://github.com/jnunemaker/httparty/pull/714)
|
10
|
+
* [Switch `:pem` option to to `OpenSSL::PKey.read` to support other algorithms](https://github.com/jnunemaker/httparty/pull/720)
|
11
|
+
|
12
|
+
## 0.19.1
|
13
|
+
|
14
|
+
* [Remove use of unary + method for creating non-frozen string to increase compatibility with older versions of ruby](https://github.com/jnunemaker/httparty/commit/4416141d37fd71bdba4f37589ec265f55aa446ce)
|
15
|
+
|
16
|
+
## 0.19.0
|
17
|
+
|
18
|
+
* [Multipart/Form-Data: rewind files after read](https://github.com/jnunemaker/httparty/pull/709)
|
19
|
+
* [add frozen_string_literal pragma to all files](https://github.com/jnunemaker/httparty/pull/711)
|
20
|
+
* [Better handling of Accept-Encoding / Content-Encoding decompression (fixes #562)](https://github.com/jnunemaker/httparty/pull/729)
|
21
|
+
|
22
|
+
## 0.18.1
|
23
|
+
|
24
|
+
* [Rename cop Lint/HandleExceptions to Lint/SuppressedException](https://github.com/jnunemaker/httparty/pull/699).
|
25
|
+
* [Encode keys in query params](https://github.com/jnunemaker/httparty/pull/698).
|
26
|
+
* [Fixed SSL doc example](https://github.com/jnunemaker/httparty/pull/692).
|
27
|
+
* [Add a build status badge](https://github.com/jnunemaker/httparty/pull/701).
|
28
|
+
|
29
|
+
|
30
|
+
## 0.18.0
|
31
|
+
|
32
|
+
* [Support gzip/deflate transfer encoding when explicit headers are set](https://github.com/jnunemaker/httparty/pull/678).
|
33
|
+
* [Support edge case cookie format with a blank attribute](https://github.com/jnunemaker/httparty/pull/685).
|
34
|
+
|
35
|
+
## 0.17.3
|
36
|
+
|
37
|
+
0.17.2 is broken https://github.com/jnunemaker/httparty/issues/681
|
38
|
+
|
39
|
+
## 0.17.2
|
40
|
+
|
41
|
+
* [Add Response#nil? deprecetion warning](https://github.com/jnunemaker/httparty/pull/680)
|
42
|
+
|
43
|
+
## 0.17.1
|
44
|
+
|
45
|
+
* [Pass options to dynamic block headers](https://github.com/jnunemaker/httparty/pull/661)
|
46
|
+
* [Normalize urls with URI adapter to allow International Domain Names support](https://github.com/jnunemaker/httparty/pull/668)
|
47
|
+
* [Add max_retries support](https://github.com/jnunemaker/httparty/pull/660)
|
48
|
+
* [Minize gem size by removing test files](https://github.com/jnunemaker/httparty/pull/658)
|
49
|
+
|
50
|
+
## 0.17.0
|
51
|
+
|
52
|
+
* [Fix encoding of streamed chunk](https://github.com/jnunemaker/httparty/pull/644)
|
53
|
+
* [Avoid modifying frozen strings](https://github.com/jnunemaker/httparty/pull/649)
|
54
|
+
* [Expose .connection on fragment block param](https://github.com/jnunemaker/httparty/pull/648)
|
55
|
+
* [Add support for `Net::HTTP#write_timeout` method (Ruby 2.6.0)](https://github.com/jnunemaker/httparty/pull/647)
|
1
56
|
|
2
57
|
## 0.16.4
|
3
58
|
* [Add support for Ruby 2.6](https://github.com/jnunemaker/httparty/pull/636)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# httparty
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/jnunemaker/httparty.svg?branch=master)](https://travis-ci.org/jnunemaker/httparty)
|
4
|
+
|
3
5
|
Makes http fun again! Ain't no party like a httparty, because a httparty don't stop.
|
4
6
|
|
5
7
|
## Install
|
@@ -10,7 +12,7 @@ gem install httparty
|
|
10
12
|
|
11
13
|
## Requirements
|
12
14
|
|
13
|
-
* Ruby 2.
|
15
|
+
* Ruby 2.3.0 or higher
|
14
16
|
* multi_xml
|
15
17
|
* You like to party!
|
16
18
|
|
@@ -46,7 +48,6 @@ puts stack_exchange.users
|
|
46
48
|
```
|
47
49
|
|
48
50
|
See the [examples directory](http://github.com/jnunemaker/httparty/tree/master/examples) for even more goodies.
|
49
|
-
|
50
51
|
## Command Line Interface
|
51
52
|
|
52
53
|
httparty also includes the executable `httparty` which can be
|
@@ -63,9 +64,8 @@ httparty "https://api.stackexchange.com/2.2/questions?site=stackoverflow"
|
|
63
64
|
## Help and Docs
|
64
65
|
|
65
66
|
* [Docs](https://github.com/jnunemaker/httparty/tree/master/docs)
|
66
|
-
* https://
|
67
|
+
* https://github.com/jnunemaker/httparty/discussions
|
67
68
|
* https://www.rubydoc.info/github/jnunemaker/httparty
|
68
|
-
* http://stackoverflow.com/questions/tagged/httparty
|
69
69
|
|
70
70
|
## Contributing
|
71
71
|
|
data/docs/README.md
CHANGED
@@ -9,7 +9,7 @@ Makes http fun again!
|
|
9
9
|
## Parsing JSON
|
10
10
|
If the response Content Type is `application/json`, HTTParty will parse the response and return Ruby objects such as a hash or array. The default behavior for parsing JSON will return keys as strings. This can be supressed with the `format` option. To get hash keys as symbols:
|
11
11
|
|
12
|
-
```
|
12
|
+
```ruby
|
13
13
|
response = HTTParty.get('http://example.com', format: :plain)
|
14
14
|
JSON.parse response, symbolize_names: true
|
15
15
|
```
|
@@ -70,7 +70,7 @@ class Client
|
|
70
70
|
end
|
71
71
|
```
|
72
72
|
|
73
|
-
You can also include
|
73
|
+
You can also include all of these options with the call:
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
class Client
|
@@ -79,14 +79,14 @@ class Client
|
|
79
79
|
base_uri "https://example.com"
|
80
80
|
|
81
81
|
def self.fetch
|
82
|
-
get("/resources", pem:
|
82
|
+
get("/resources", pem: File.read("#{File.expand_path('.')}/path/to/certs/cert.pem"), pem_password: "123456")
|
83
83
|
end
|
84
84
|
end
|
85
85
|
```
|
86
86
|
|
87
87
|
### Avoid SSL verification
|
88
88
|
|
89
|
-
In some cases you may want to skip SSL verification, because the entity that
|
89
|
+
In some cases you may want to skip SSL verification, because the entity that issued the certificate is not a valid one, but you still want to work with it. You can achieve this through:
|
90
90
|
|
91
91
|
```ruby
|
92
92
|
# Skips SSL certificate verification
|
@@ -103,4 +103,69 @@ class Client
|
|
103
103
|
# get("resources", verify_peer: false)
|
104
104
|
end
|
105
105
|
end
|
106
|
-
```
|
106
|
+
```
|
107
|
+
|
108
|
+
### HTTP Compression
|
109
|
+
|
110
|
+
The `Accept-Encoding` request header and `Content-Encoding` response header
|
111
|
+
are used to control compression (gzip, etc.) over the wire. Refer to
|
112
|
+
[RFC-2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) for details.
|
113
|
+
(For clarity: these headers are **not** used for character encoding i.e. `utf-8`
|
114
|
+
which is specified in the `Accept` and `Content-Type` headers.)
|
115
|
+
|
116
|
+
Unless you have specific requirements otherwise, we recommend to **not** set
|
117
|
+
set the `Accept-Encoding` header on HTTParty requests. In this case, `Net::HTTP`
|
118
|
+
will set a sensible default compression scheme and automatically decompress the response.
|
119
|
+
|
120
|
+
If you explicitly set `Accept-Encoding`, there be dragons:
|
121
|
+
|
122
|
+
* If the HTTP response `Content-Encoding` received on the wire is `gzip` or `deflate`,
|
123
|
+
`Net::HTTP` will automatically decompress it, and will omit `Content-Encoding`
|
124
|
+
from your `HTTParty::Response` headers.
|
125
|
+
|
126
|
+
* For encodings `br` (Brotli) or `compress` (LZW), HTTParty will automatically
|
127
|
+
decompress if you include the `brotli` or `ruby-lzws` gems respectively into your project.
|
128
|
+
**Warning:** Support for these encodings is experimental and not fully battle-tested.
|
129
|
+
Similar to above, if decompression succeeds, `Content-Encoding` will be omitted
|
130
|
+
from your `HTTParty::Response` headers.
|
131
|
+
|
132
|
+
* For other encodings, `HTTParty::Response#body` will return the raw uncompressed byte string,
|
133
|
+
and you'll need to inspect the `Content-Encoding` response header and decompress it yourself.
|
134
|
+
In this case, `HTTParty::Response#parsed_response` will be `nil`.
|
135
|
+
|
136
|
+
* Lastly, you may use the `skip_decompression` option to disable all automatic decompression
|
137
|
+
and always get `HTTParty::Response#body` in its raw form along with the `Content-Encoding` header.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
# Accept-Encoding=gzip,deflate can be safely assumed to be auto-decompressed
|
141
|
+
|
142
|
+
res = HTTParty.get('https://example.com/test.json', headers: { 'Accept-Encoding' => 'gzip,deflate,identity' })
|
143
|
+
JSON.parse(res.body) # safe
|
144
|
+
|
145
|
+
|
146
|
+
# Accept-Encoding=br,compress requires third-party gems
|
147
|
+
|
148
|
+
require 'brotli'
|
149
|
+
require 'lzws'
|
150
|
+
res = HTTParty.get('https://example.com/test.json', headers: { 'Accept-Encoding' => 'br,compress' })
|
151
|
+
JSON.parse(res.body)
|
152
|
+
|
153
|
+
|
154
|
+
# Accept-Encoding=* may return unhandled Content-Encoding
|
155
|
+
|
156
|
+
res = HTTParty.get('https://example.com/test.json', headers: { 'Accept-Encoding' => '*' })
|
157
|
+
encoding = res.headers['Content-Encoding']
|
158
|
+
if encoding
|
159
|
+
JSON.parse(your_decompression_handling(res.body, encoding))
|
160
|
+
else
|
161
|
+
# Content-Encoding not present implies decompressed
|
162
|
+
JSON.parse(res.body)
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# Gimme the raw data!
|
167
|
+
|
168
|
+
res = HTTParty.get('https://example.com/test.json', skip_decompression: true)
|
169
|
+
encoding = res.headers['Content-Encoding']
|
170
|
+
JSON.parse(your_decompression_handling(res.body, encoding))
|
171
|
+
```
|
data/examples/README.md
CHANGED
@@ -81,3 +81,9 @@
|
|
81
81
|
|
82
82
|
* [Uploading File](body_stream.rb)
|
83
83
|
* Uses `body_stream` to upload file
|
84
|
+
|
85
|
+
* [Accessing x509 Peer Certificate](peer_cert.rb)
|
86
|
+
* Provides access to the server's TLS certificate
|
87
|
+
|
88
|
+
* [Accessing IDNs](idn.rb)
|
89
|
+
* Uses a `get` request with an International domain names, which are Urls with emojis and non-ASCII characters such as accented letters.
|
data/examples/aaws.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'active_support'
|
3
|
+
require 'active_support/core_ext/hash'
|
4
|
+
require 'active_support/core_ext/string'
|
3
5
|
|
4
6
|
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
7
|
require File.join(dir, 'httparty')
|
@@ -13,14 +15,16 @@ module AAWS
|
|
13
15
|
default_params Service: 'AWSECommerceService', Operation: 'ItemSearch', SearchIndex: 'Books'
|
14
16
|
|
15
17
|
def initialize(key)
|
16
|
-
|
18
|
+
@auth = { AWSAccessKeyId: key }
|
17
19
|
end
|
18
20
|
|
19
21
|
def search(options = {})
|
20
22
|
raise ArgumentError, 'You must search for something' if options[:query].blank?
|
21
23
|
|
22
24
|
# amazon uses nasty camelized query params
|
23
|
-
options[:query] = options[:query]
|
25
|
+
options[:query] = options[:query]
|
26
|
+
.reverse_merge(@auth)
|
27
|
+
.transform_keys { |k| k.to_s.camelize }
|
24
28
|
|
25
29
|
# make a request and return the items (NOTE: this doesn't handle errors at this point)
|
26
30
|
self.class.get('/onca/xml', options)['ItemSearchResponse']['Items']
|
data/examples/idn.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
|
4
|
+
peer_cert = nil
|
5
|
+
HTTParty.get("https://www.example.com") do |fragment|
|
6
|
+
peer_cert ||= fragment.connection.peer_cert
|
7
|
+
end
|
8
|
+
|
9
|
+
puts "The server's certificate expires #{peer_cert.not_after}"
|
data/httparty.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.summary = 'Makes http fun! Also, makes consuming restful web services dead easy.'
|
14
14
|
s.description = 'Makes http fun! Also, makes consuming restful web services dead easy.'
|
15
15
|
|
16
|
-
s.required_ruby_version = '>= 2.
|
16
|
+
s.required_ruby_version = '>= 2.3.0'
|
17
17
|
|
18
18
|
s.add_dependency 'multi_xml', ">= 0.5.2"
|
19
19
|
s.add_dependency('mime-types', "~> 3.0")
|
@@ -25,7 +25,6 @@ Gem::Specification.new do |s|
|
|
25
25
|
test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
26
|
|
27
27
|
s.files = all_files - test_files
|
28
|
-
s.test_files = test_files
|
29
28
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
30
29
|
s.require_paths = ["lib"]
|
31
30
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTParty
|
2
4
|
# Default connection adapter that returns a new Net::HTTP each time
|
3
5
|
#
|
@@ -42,6 +44,7 @@ module HTTParty
|
|
42
44
|
# * :+timeout+: timeout in seconds
|
43
45
|
# * :+open_timeout+: http connection open_timeout in seconds, overrides timeout if set
|
44
46
|
# * :+read_timeout+: http connection read_timeout in seconds, overrides timeout if set
|
47
|
+
# * :+write_timeout+: http connection write_timeout in seconds, overrides timeout if set (Ruby >= 2.6.0 required)
|
45
48
|
# * :+debug_output+: see HTTParty::ClassMethods.debug_output.
|
46
49
|
# * :+cert_store+: contains certificate data. see method 'attach_ssl_certificates'
|
47
50
|
# * :+pem+: contains pem client certificate data. see method 'attach_ssl_certificates'
|
@@ -113,19 +116,35 @@ module HTTParty
|
|
113
116
|
|
114
117
|
attach_ssl_certificates(http, options)
|
115
118
|
|
116
|
-
if
|
119
|
+
if add_timeout?(options[:timeout])
|
117
120
|
http.open_timeout = options[:timeout]
|
118
121
|
http.read_timeout = options[:timeout]
|
122
|
+
|
123
|
+
from_ruby_version('2.6.0', option: :write_timeout, warn: false) do
|
124
|
+
http.write_timeout = options[:timeout]
|
125
|
+
end
|
119
126
|
end
|
120
127
|
|
121
|
-
if
|
128
|
+
if add_timeout?(options[:read_timeout])
|
122
129
|
http.read_timeout = options[:read_timeout]
|
123
130
|
end
|
124
131
|
|
125
|
-
if
|
132
|
+
if add_timeout?(options[:open_timeout])
|
126
133
|
http.open_timeout = options[:open_timeout]
|
127
134
|
end
|
128
135
|
|
136
|
+
if add_timeout?(options[:write_timeout])
|
137
|
+
from_ruby_version('2.6.0', option: :write_timeout) do
|
138
|
+
http.write_timeout = options[:write_timeout]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
if add_max_retries?(options[:max_retries])
|
143
|
+
from_ruby_version('2.5.0', option: :max_retries) do
|
144
|
+
http.max_retries = options[:max_retries]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
129
148
|
if options[:debug_output]
|
130
149
|
http.set_debug_output(options[:debug_output])
|
131
150
|
end
|
@@ -138,18 +157,14 @@ module HTTParty
|
|
138
157
|
#
|
139
158
|
# @see https://bugs.ruby-lang.org/issues/6617
|
140
159
|
if options[:local_host]
|
141
|
-
|
160
|
+
from_ruby_version('2.0.0', option: :local_host) do
|
142
161
|
http.local_host = options[:local_host]
|
143
|
-
else
|
144
|
-
Kernel.warn("Warning: option :local_host requires Ruby version 2.0 or later")
|
145
162
|
end
|
146
163
|
end
|
147
164
|
|
148
165
|
if options[:local_port]
|
149
|
-
|
166
|
+
from_ruby_version('2.0.0', option: :local_port) do
|
150
167
|
http.local_port = options[:local_port]
|
151
|
-
else
|
152
|
-
Kernel.warn("Warning: option :local_port requires Ruby version 2.0 or later")
|
153
168
|
end
|
154
169
|
end
|
155
170
|
|
@@ -158,6 +173,22 @@ module HTTParty
|
|
158
173
|
|
159
174
|
private
|
160
175
|
|
176
|
+
def from_ruby_version(ruby_version, option: nil, warn: true)
|
177
|
+
if RUBY_VERSION >= ruby_version
|
178
|
+
yield
|
179
|
+
elsif warn
|
180
|
+
Kernel.warn("Warning: option #{ option } requires Ruby version #{ ruby_version } or later")
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_timeout?(timeout)
|
185
|
+
timeout && (timeout.is_a?(Integer) || timeout.is_a?(Float))
|
186
|
+
end
|
187
|
+
|
188
|
+
def add_max_retries?(max_retries)
|
189
|
+
max_retries && max_retries.is_a?(Integer) && max_retries >= 0
|
190
|
+
end
|
191
|
+
|
161
192
|
def clean_host(host)
|
162
193
|
strip_ipv6_brackets(host)
|
163
194
|
end
|
@@ -192,7 +223,7 @@ module HTTParty
|
|
192
223
|
# Note: options[:pem] must contain the content of a PEM file having the private key appended
|
193
224
|
if options[:pem]
|
194
225
|
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
|
195
|
-
http.key = OpenSSL::PKey
|
226
|
+
http.key = OpenSSL::PKey.read(options[:pem], options[:pem_password])
|
196
227
|
http.verify_mode = verify_ssl_certificate? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
197
228
|
end
|
198
229
|
|
data/lib/httparty/cookie_hash.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class HTTParty::CookieHash < Hash #:nodoc:
|
2
|
-
CLIENT_COOKIES = %w(path expires domain path secure httponly)
|
4
|
+
CLIENT_COOKIES = %w(path expires domain path secure httponly samesite)
|
3
5
|
|
4
|
-
def add_cookies(
|
5
|
-
case
|
6
|
+
def add_cookies(data)
|
7
|
+
case data
|
6
8
|
when Hash
|
7
|
-
merge!(
|
9
|
+
merge!(data)
|
8
10
|
when String
|
9
|
-
|
10
|
-
|
11
|
-
self[
|
11
|
+
data.split('; ').each do |cookie|
|
12
|
+
key, value = cookie.split('=', 2)
|
13
|
+
self[key.to_sym] = value if key
|
12
14
|
end
|
13
15
|
else
|
14
16
|
raise "add_cookies only takes a Hash or a String"
|
@@ -16,6 +18,6 @@ class HTTParty::CookieHash < Hash #:nodoc:
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def to_cookie_string
|
19
|
-
select { |k, v| !CLIENT_COOKIES.include?(k.to_s.downcase) }.collect { |k, v| "#{k}=#{v}" }.join(
|
21
|
+
select { |k, v| !CLIENT_COOKIES.include?(k.to_s.downcase) }.collect { |k, v| "#{k}=#{v}" }.join('; ')
|
20
22
|
end
|
21
23
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTParty
|
4
|
+
# Decompresses the response body based on the Content-Encoding header.
|
5
|
+
#
|
6
|
+
# Net::HTTP automatically decompresses Content-Encoding values "gzip" and "deflate".
|
7
|
+
# This class will handle "br" (Brotli) and "compress" (LZW) if the requisite
|
8
|
+
# gems are installed. Otherwise, it returns nil if the body data cannot be
|
9
|
+
# decompressed.
|
10
|
+
#
|
11
|
+
# @abstract Read the HTTP Compression section for more information.
|
12
|
+
class Decompressor
|
13
|
+
|
14
|
+
# "gzip" and "deflate" are handled by Net::HTTP
|
15
|
+
# hence they do not need to be handled by HTTParty
|
16
|
+
SupportedEncodings = {
|
17
|
+
'none' => :none,
|
18
|
+
'identity' => :none,
|
19
|
+
'br' => :brotli,
|
20
|
+
'compress' => :lzw
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
# The response body of the request
|
24
|
+
# @return [String]
|
25
|
+
attr_reader :body
|
26
|
+
|
27
|
+
# The Content-Encoding algorithm used to encode the body
|
28
|
+
# @return [Symbol] e.g. :gzip
|
29
|
+
attr_reader :encoding
|
30
|
+
|
31
|
+
# @param [String] body - the response body of the request
|
32
|
+
# @param [Symbol] encoding - the Content-Encoding algorithm used to encode the body
|
33
|
+
def initialize(body, encoding)
|
34
|
+
@body = body
|
35
|
+
@encoding = encoding
|
36
|
+
end
|
37
|
+
|
38
|
+
# Perform decompression on the response body
|
39
|
+
# @return [String] the decompressed body
|
40
|
+
# @return [nil] when the response body is nil or cannot decompressed
|
41
|
+
def decompress
|
42
|
+
return nil if body.nil?
|
43
|
+
return body if encoding.nil? || encoding.strip.empty?
|
44
|
+
|
45
|
+
if supports_encoding?
|
46
|
+
decompress_supported_encoding
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def supports_encoding?
|
55
|
+
SupportedEncodings.keys.include?(encoding)
|
56
|
+
end
|
57
|
+
|
58
|
+
def decompress_supported_encoding
|
59
|
+
method = SupportedEncodings[encoding]
|
60
|
+
if respond_to?(method, true)
|
61
|
+
send(method)
|
62
|
+
else
|
63
|
+
raise NotImplementedError, "#{self.class.name} has not implemented a decompression method for #{encoding.inspect} encoding."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def none
|
68
|
+
body
|
69
|
+
end
|
70
|
+
|
71
|
+
def brotli
|
72
|
+
return nil unless defined?(::Brotli)
|
73
|
+
begin
|
74
|
+
::Brotli.inflate(body)
|
75
|
+
rescue StandardError
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def lzw
|
81
|
+
begin
|
82
|
+
if defined?(::LZWS::String)
|
83
|
+
::LZWS::String.decompress(body)
|
84
|
+
elsif defined?(::LZW::Simple)
|
85
|
+
::LZW::Simple.new.decompress(body)
|
86
|
+
end
|
87
|
+
rescue StandardError
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/httparty/exceptions.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTParty
|
2
|
-
# @
|
4
|
+
# @abstract Exceptions raised by HTTParty inherit from Error
|
3
5
|
class Error < StandardError; end
|
4
6
|
|
5
7
|
# Exception raised when you attempt to set a non-existent format
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'erb'
|
2
4
|
|
3
5
|
module HTTParty
|
@@ -26,8 +28,8 @@ module HTTParty
|
|
26
28
|
def self.normalize_param(key, value)
|
27
29
|
normalized_keys = normalize_keys(key, value)
|
28
30
|
|
29
|
-
normalized_keys.flatten.each_slice(2).inject('') do |string, (k, v)|
|
30
|
-
string
|
31
|
+
normalized_keys.flatten.each_slice(2).inject(''.dup) do |string, (k, v)|
|
32
|
+
string << "#{ERB::Util.url_encode(k)}=#{ERB::Util.url_encode(v.to_s)}&"
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTParty
|
4
|
+
class HeadersProcessor
|
5
|
+
attr_reader :headers, :options
|
6
|
+
|
7
|
+
def initialize(headers, options)
|
8
|
+
@headers = headers
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
return unless options[:headers]
|
14
|
+
|
15
|
+
options[:headers] = headers.merge(options[:headers]) if headers.any?
|
16
|
+
options[:headers] = Utils.stringify_keys(process_dynamic_headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def process_dynamic_headers
|
22
|
+
options[:headers].each_with_object({}) do |header, processed_headers|
|
23
|
+
key, value = header
|
24
|
+
processed_headers[key] = if value.respond_to?(:call)
|
25
|
+
value.arity == 0 ? value.call : value.call(options)
|
26
|
+
else
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTParty
|
2
4
|
module Logger
|
3
5
|
class ApacheFormatter #:nodoc:
|
@@ -26,11 +28,11 @@ module HTTParty
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def current_time
|
29
|
-
Time.now.strftime(
|
31
|
+
Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
30
32
|
end
|
31
33
|
|
32
34
|
def http_method
|
33
|
-
request.http_method.name.split(
|
35
|
+
request.http_method.name.split('::').last.upcase
|
34
36
|
end
|
35
37
|
|
36
38
|
def path
|