httparty 0.13.7 → 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/.editorconfig +18 -0
- data/.github/workflows/ci.yml +23 -0
- data/.gitignore +2 -0
- data/.rubocop_todo.yml +1 -1
- data/{History → Changelog.md} +220 -59
- data/Gemfile +8 -3
- data/README.md +8 -7
- data/bin/httparty +3 -1
- data/docs/README.md +171 -0
- data/examples/README.md +34 -12
- data/examples/aaws.rb +7 -3
- data/examples/body_stream.rb +14 -0
- data/examples/crack.rb +1 -1
- data/examples/custom_parsers.rb +5 -1
- data/examples/delicious.rb +4 -4
- data/examples/headers_and_user_agents.rb +7 -3
- data/examples/idn.rb +10 -0
- data/examples/logging.rb +4 -4
- data/examples/microsoft_graph.rb +52 -0
- data/examples/multipart.rb +22 -0
- data/examples/peer_cert.rb +9 -0
- data/examples/stackexchange.rb +1 -1
- data/examples/stream_download.rb +26 -0
- data/examples/tripit_sign_in.rb +17 -6
- data/examples/twitter.rb +2 -2
- data/examples/whoismyrep.rb +1 -1
- data/httparty.gemspec +7 -5
- data/lib/httparty/connection_adapter.rb +86 -20
- data/lib/httparty/cookie_hash.rb +10 -8
- data/lib/httparty/decompressor.rb +92 -0
- data/lib/httparty/exceptions.rb +8 -2
- data/lib/httparty/hash_conversions.rb +30 -8
- data/lib/httparty/headers_processor.rb +32 -0
- data/lib/httparty/logger/apache_formatter.rb +31 -6
- data/lib/httparty/logger/curl_formatter.rb +68 -23
- data/lib/httparty/logger/logger.rb +5 -1
- data/lib/httparty/logger/logstash_formatter.rb +61 -0
- data/lib/httparty/module_inheritable_attributes.rb +6 -4
- data/lib/httparty/net_digest_auth.rb +23 -21
- data/lib/httparty/parser.rb +25 -14
- data/lib/httparty/request/body.rb +98 -0
- data/lib/httparty/request/multipart_boundary.rb +13 -0
- data/lib/httparty/request.rb +156 -106
- data/lib/httparty/response/headers.rb +23 -19
- data/lib/httparty/response.rb +92 -13
- data/lib/httparty/response_fragment.rb +21 -0
- data/lib/httparty/text_encoder.rb +72 -0
- data/lib/httparty/utils.rb +13 -0
- data/lib/httparty/version.rb +3 -1
- data/lib/httparty.rb +98 -34
- data/website/css/common.css +1 -1
- metadata +34 -113
- data/.travis.yml +0 -7
- 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 -52
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -90
- 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/google.html +0 -3
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/1fe462c2.0 +0 -16
- 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/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 -468
- data/spec/httparty/cookie_hash_spec.rb +0 -83
- data/spec/httparty/exception_spec.rb +0 -38
- data/spec/httparty/hash_conversions_spec.rb +0 -41
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -18
- data/spec/httparty/logger/logger_spec.rb +0 -38
- data/spec/httparty/net_digest_auth_spec.rb +0 -230
- data/spec/httparty/parser_spec.rb +0 -173
- data/spec/httparty/request_spec.rb +0 -1073
- data/spec/httparty/response_spec.rb +0 -241
- data/spec/httparty/ssl_spec.rb +0 -74
- data/spec/httparty_spec.rb +0 -850
- data/spec/spec_helper.rb +0 -59
- 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
data/bin/httparty
CHANGED
@@ -103,9 +103,11 @@ else
|
|
103
103
|
when :json
|
104
104
|
begin
|
105
105
|
require 'json'
|
106
|
-
puts JSON.pretty_generate(response)
|
106
|
+
puts JSON.pretty_generate(response.parsed_response)
|
107
107
|
rescue LoadError
|
108
108
|
puts YAML.dump(response)
|
109
|
+
rescue JSON::JSONError
|
110
|
+
puts response.inspect
|
109
111
|
end
|
110
112
|
when :xml
|
111
113
|
require 'rexml/document'
|
data/docs/README.md
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
# httparty
|
2
|
+
|
3
|
+
Makes http fun again!
|
4
|
+
|
5
|
+
## Table of contents
|
6
|
+
- [Parsing JSON](#parsing-json)
|
7
|
+
- [Working with SSL](#working-with-ssl)
|
8
|
+
|
9
|
+
## Parsing JSON
|
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
|
+
|
12
|
+
```ruby
|
13
|
+
response = HTTParty.get('http://example.com', format: :plain)
|
14
|
+
JSON.parse response, symbolize_names: true
|
15
|
+
```
|
16
|
+
|
17
|
+
## Working with SSL
|
18
|
+
|
19
|
+
You can use this guide to work with SSL certificates.
|
20
|
+
|
21
|
+
#### Using `pem` option
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# Use this example if you are using a pem file
|
25
|
+
|
26
|
+
class Client
|
27
|
+
include HTTParty
|
28
|
+
|
29
|
+
base_uri "https://example.com"
|
30
|
+
pem File.read("#{File.expand_path('.')}/path/to/certs/cert.pem"), "123456"
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
#### Using `pkcs12` option
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# Use this example if you are using a pkcs12 file
|
38
|
+
|
39
|
+
class Client
|
40
|
+
include HTTParty
|
41
|
+
|
42
|
+
base_uri "https://example.com"
|
43
|
+
pkcs12 File.read("#{File.expand_path('.')}/path/to/certs/cert.p12"), "123456"
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
#### Using `ssl_ca_file` option
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# Use this example if you are using a pkcs12 file
|
51
|
+
|
52
|
+
class Client
|
53
|
+
include HTTParty
|
54
|
+
|
55
|
+
base_uri "https://example.com"
|
56
|
+
ssl_ca_file "#{File.expand_path('.')}/path/to/certs/cert.pem"
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
#### Using `ssl_ca_path` option
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# Use this example if you are using a pkcs12 file
|
64
|
+
|
65
|
+
class Client
|
66
|
+
include HTTParty
|
67
|
+
|
68
|
+
base_uri "https://example.com"
|
69
|
+
ssl_ca_path '/path/to/certs'
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
You can also include all of these options with the call:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class Client
|
77
|
+
include HTTParty
|
78
|
+
|
79
|
+
base_uri "https://example.com"
|
80
|
+
|
81
|
+
def self.fetch
|
82
|
+
get("/resources", pem: File.read("#{File.expand_path('.')}/path/to/certs/cert.pem"), pem_password: "123456")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
### Avoid SSL verification
|
88
|
+
|
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
|
+
|
91
|
+
```ruby
|
92
|
+
# Skips SSL certificate verification
|
93
|
+
|
94
|
+
class Client
|
95
|
+
include HTTParty
|
96
|
+
|
97
|
+
base_uri "https://example.com"
|
98
|
+
pem File.read("#{File.expand_path('.')}/path/to/certs/cert.pem"), "123456"
|
99
|
+
|
100
|
+
def self.fetch
|
101
|
+
get("/resources", verify: false)
|
102
|
+
# You can also use something like:
|
103
|
+
# get("resources", verify_peer: false)
|
104
|
+
end
|
105
|
+
end
|
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
@@ -13,22 +13,22 @@
|
|
13
13
|
* Creates a custom parser for XML using crack gem
|
14
14
|
* Uses `get` request
|
15
15
|
|
16
|
-
* [Create HTML Nokogiri parser](nokogiri_html_parser.rb)
|
16
|
+
* [Create HTML Nokogiri parser](nokogiri_html_parser.rb)
|
17
17
|
* Adds Html as a format
|
18
18
|
* passed the body of request to Nokogiri
|
19
|
-
|
19
|
+
|
20
20
|
* [More Custom Parsers](custom_parsers.rb)
|
21
21
|
* Create an additional parser for atom or make it the ONLY parser
|
22
|
-
|
22
|
+
|
23
23
|
* [Basic Auth, Delicious](delicious.rb)
|
24
24
|
* Basic Auth, shows how to merge those into options
|
25
25
|
* Uses `get` requests
|
26
|
-
|
26
|
+
|
27
27
|
* [Passing Headers, User Agent](headers_and_user_agents.rb)
|
28
28
|
* Use the class method of Httparty
|
29
29
|
* Pass the User-Agent in the headers
|
30
30
|
* Uses `get` requests
|
31
|
-
|
31
|
+
|
32
32
|
* [Basic Post Request](basic.rb)
|
33
33
|
* Httparty included into poro class
|
34
34
|
* Uses `post` requests
|
@@ -36,7 +36,7 @@
|
|
36
36
|
* [Access Rubyurl Shortener](rubyurl.rb)
|
37
37
|
* Httparty included into poro class
|
38
38
|
* Uses `post` requests
|
39
|
-
|
39
|
+
|
40
40
|
* [Add a custom log file](logging.rb)
|
41
41
|
* create a log file and have httparty log requests
|
42
42
|
|
@@ -44,24 +44,46 @@
|
|
44
44
|
* Httparty included into poro class
|
45
45
|
* Creates methods for different endpoints
|
46
46
|
* Uses `get` requests
|
47
|
-
|
47
|
+
|
48
48
|
* [Accessing Tripit](tripit_sign_in.rb)
|
49
49
|
* Httparty included into poro class
|
50
50
|
* Example of using `debug_output` to see headers/urls passed
|
51
51
|
* Getting and using Cookies
|
52
52
|
* Uses `get` requests
|
53
|
-
|
53
|
+
|
54
54
|
* [Accessing Twitter](twitter.rb)
|
55
55
|
* Httparty included into poro class
|
56
56
|
* Basic Auth
|
57
|
-
* Loads settings from a config file
|
57
|
+
* Loads settings from a config file
|
58
58
|
* Uses `get` requests
|
59
59
|
* Uses `post` requests
|
60
|
-
|
60
|
+
|
61
61
|
* [Accessing WhoIsMyRep](whoismyrep.rb)
|
62
62
|
* Httparty included into poro class
|
63
|
-
* Uses `get` requests
|
63
|
+
* Uses `get` requests
|
64
64
|
* Two ways to pass params to get, inline on the url or in query hash
|
65
65
|
|
66
66
|
* [Rescue Json Error](rescue_json.rb)
|
67
|
-
* Rescue errors due to parsing response
|
67
|
+
* Rescue errors due to parsing response
|
68
|
+
|
69
|
+
* [Download file using stream mode](stream_download.rb)
|
70
|
+
* Uses `get` requests
|
71
|
+
* Uses `stream_body` mode
|
72
|
+
* Download file without using the memory
|
73
|
+
|
74
|
+
* [Microsoft graph](microsoft_graph.rb)
|
75
|
+
* Basic Auth
|
76
|
+
* Uses `post` requests
|
77
|
+
* Uses multipart
|
78
|
+
|
79
|
+
* [Multipart](multipart.rb)
|
80
|
+
* Multipart data upload _(with and without file)_
|
81
|
+
|
82
|
+
* [Uploading File](body_stream.rb)
|
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']
|
@@ -29,4 +33,4 @@ module AAWS
|
|
29
33
|
end
|
30
34
|
|
31
35
|
aaws = AAWS::Book.new(config[:access_key])
|
32
|
-
pp aaws.search(query: {title: 'Ruby On Rails'})
|
36
|
+
pp aaws.search(query: { title: 'Ruby On Rails' })
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# To upload file to a server use :body_stream
|
2
|
+
|
3
|
+
HTTParty.put(
|
4
|
+
'http://localhost:3000/train',
|
5
|
+
body_stream: File.open('sample_configs/config_train_server_md.yml', 'r')
|
6
|
+
)
|
7
|
+
|
8
|
+
|
9
|
+
# Actually, it works with any IO object
|
10
|
+
|
11
|
+
HTTParty.put(
|
12
|
+
'http://localhost:3000/train',
|
13
|
+
body_stream: StringIO.new('foo')
|
14
|
+
)
|
data/examples/crack.rb
CHANGED
@@ -16,4 +16,4 @@ class Rep
|
|
16
16
|
end
|
17
17
|
|
18
18
|
pp Rep.get('http://whoismyrepresentative.com/getall_mems.php?zip=46544')
|
19
|
-
pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', query: {zip: 46544})
|
19
|
+
pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', query: { zip: 46544 })
|
data/examples/custom_parsers.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
|
1
5
|
class ParseAtom
|
2
6
|
include HTTParty
|
3
7
|
|
@@ -21,7 +25,7 @@ class OnlyParseAtom
|
|
21
25
|
|
22
26
|
# Only support Atom
|
23
27
|
class Parser::OnlyAtom < HTTParty::Parser
|
24
|
-
SupportedFormats = {"application/atom+xml" => :atom}
|
28
|
+
SupportedFormats = { "application/atom+xml" => :atom }
|
25
29
|
|
26
30
|
protected
|
27
31
|
|
data/examples/delicious.rb
CHANGED
@@ -8,7 +8,7 @@ class Delicious
|
|
8
8
|
base_uri 'https://api.del.icio.us/v1'
|
9
9
|
|
10
10
|
def initialize(u, p)
|
11
|
-
@auth = {username: u, password: p}
|
11
|
+
@auth = { username: u, password: p }
|
12
12
|
end
|
13
13
|
|
14
14
|
# query params that filter the posts are:
|
@@ -17,7 +17,7 @@ class Delicious
|
|
17
17
|
# url (optional). Filter by this url.
|
18
18
|
# ie: posts(query: {tag: 'ruby'})
|
19
19
|
def posts(options = {})
|
20
|
-
options.merge!({basic_auth: @auth})
|
20
|
+
options.merge!({ basic_auth: @auth })
|
21
21
|
self.class.get('/posts/get', options)
|
22
22
|
end
|
23
23
|
|
@@ -25,13 +25,13 @@ class Delicious
|
|
25
25
|
# tag (optional). Filter by this tag.
|
26
26
|
# count (optional). Number of items to retrieve (Default:15, Maximum:100).
|
27
27
|
def recent(options = {})
|
28
|
-
options.merge!({basic_auth: @auth})
|
28
|
+
options.merge!({ basic_auth: @auth })
|
29
29
|
self.class.get('/posts/recent', options)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
delicious = Delicious.new(config['username'], config['password'])
|
34
|
-
pp delicious.posts(query: {tag: 'ruby'})
|
34
|
+
pp delicious.posts(query: { tag: 'ruby' })
|
35
35
|
pp delicious.recent
|
36
36
|
|
37
37
|
delicious.recent['posts']['post'].each { |post| puts post['href'] }
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# To send custom user agents to identify your application to a web service (or mask as a specific browser for testing), send "User-Agent" as a hash to headers as shown below.
|
2
2
|
|
3
|
-
|
3
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require File.join(dir, 'httparty')
|
5
|
+
require 'pp'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
response = HTTParty.get('http://example.com', {
|
8
|
+
headers: {"User-Agent" => "Httparty"},
|
9
|
+
debug_output: STDOUT, # To show that User-Agent is Httparty
|
10
|
+
})
|
data/examples/idn.rb
ADDED
data/examples/logging.rb
CHANGED
@@ -3,7 +3,7 @@ require File.join(dir, 'httparty')
|
|
3
3
|
require 'logger'
|
4
4
|
require 'pp'
|
5
5
|
|
6
|
-
my_logger = Logger.new
|
6
|
+
my_logger = Logger.new STDOUT
|
7
7
|
|
8
8
|
my_logger.info "Logging can be used on the main HTTParty class. It logs redirects too."
|
9
9
|
HTTParty.get "http://google.com", logger: my_logger
|
@@ -14,7 +14,7 @@ my_logger.info "It can be used also on a custom class."
|
|
14
14
|
|
15
15
|
class Google
|
16
16
|
include HTTParty
|
17
|
-
logger ::Logger.new
|
17
|
+
logger ::Logger.new STDOUT
|
18
18
|
end
|
19
19
|
|
20
20
|
Google.get "http://google.com"
|
@@ -22,7 +22,7 @@ Google.get "http://google.com"
|
|
22
22
|
my_logger.info '*' * 70
|
23
23
|
|
24
24
|
my_logger.info "The default formatter is :apache. The :curl formatter can also be used."
|
25
|
-
my_logger.info "You can tell
|
25
|
+
my_logger.info "You can tell which method to call on the logger too. It is info by default."
|
26
26
|
HTTParty.get "http://google.com", logger: my_logger, log_level: :debug, log_format: :curl
|
27
27
|
|
28
28
|
my_logger.info '*' * 70
|
@@ -30,7 +30,7 @@ my_logger.info '*' * 70
|
|
30
30
|
my_logger.info "These configs are also available on custom classes."
|
31
31
|
class Google
|
32
32
|
include HTTParty
|
33
|
-
logger ::Logger.new(
|
33
|
+
logger ::Logger.new(STDOUT), :debug, :curl
|
34
34
|
end
|
35
35
|
|
36
36
|
Google.get "http://google.com"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
class MicrosoftGraph
|
4
|
+
MS_BASE_URL = "https://login.microsoftonline.com".freeze
|
5
|
+
TOKEN_REQUEST_PATH = "oauth2/v2.0/token".freeze
|
6
|
+
|
7
|
+
def initialize(tenant_id)
|
8
|
+
@tenant_id = tenant_id
|
9
|
+
end
|
10
|
+
|
11
|
+
# Make a request to the Microsoft Graph API, for instance https://graph.microsoft.com/v1.0/users
|
12
|
+
def request(url)
|
13
|
+
return false unless (token = bearer_token)
|
14
|
+
|
15
|
+
response = HTTParty.get(
|
16
|
+
url,
|
17
|
+
headers: {
|
18
|
+
Authorization: "Bearer #{token}"
|
19
|
+
}
|
20
|
+
)
|
21
|
+
|
22
|
+
return false unless response.code == 200
|
23
|
+
|
24
|
+
return JSON.parse(response.body)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# A post to the Microsoft Graph to get a bearer token for the specified tenant. In this example
|
30
|
+
# our Rails application has already been given permission to request these tokens by the admin of
|
31
|
+
# the specified tenant_id.
|
32
|
+
#
|
33
|
+
# See here for more information https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
|
34
|
+
#
|
35
|
+
# This request also makes use of the multipart/form-data post body.
|
36
|
+
def bearer_token
|
37
|
+
response = HTTParty.post(
|
38
|
+
"#{MS_BASE_URL}/#{@tenant_id}/#{TOKEN_REQUEST_PATH}",
|
39
|
+
multipart: true,
|
40
|
+
body: {
|
41
|
+
client_id: Rails.application.credentials[Rails.env.to_sym][:microsoft_client_id],
|
42
|
+
client_secret: Rails.application.credentials[Rails.env.to_sym][:microsoft_client_secret],
|
43
|
+
scope: 'https://graph.microsoft.com/.default',
|
44
|
+
grant_type: 'client_credentials'
|
45
|
+
}
|
46
|
+
)
|
47
|
+
|
48
|
+
return false unless response.code == 200
|
49
|
+
|
50
|
+
JSON.parse(response.body)['access_token']
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# If you are uploading file in params, multipart will used as content-type automatically
|
2
|
+
|
3
|
+
HTTParty.post(
|
4
|
+
'http://localhost:3000/user',
|
5
|
+
body: {
|
6
|
+
name: 'Foo Bar',
|
7
|
+
email: 'example@email.com',
|
8
|
+
avatar: File.open('/full/path/to/avatar.jpg')
|
9
|
+
}
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
# However, you can force it yourself
|
14
|
+
|
15
|
+
HTTParty.post(
|
16
|
+
'http://localhost:3000/user',
|
17
|
+
multipart: true,
|
18
|
+
body: {
|
19
|
+
name: 'Foo Bar',
|
20
|
+
email: 'example@email.com'
|
21
|
+
}
|
22
|
+
)
|
@@ -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/examples/stackexchange.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
# download file linux-4.6.4.tar.xz without using the memory
|
6
|
+
response = nil
|
7
|
+
filename = "linux-4.6.4.tar.xz"
|
8
|
+
url = "https://cdn.kernel.org/pub/linux/kernel/v4.x/#{filename}"
|
9
|
+
|
10
|
+
File.open(filename, "w") do |file|
|
11
|
+
response = HTTParty.get(url, stream_body: true) do |fragment|
|
12
|
+
if [301, 302].include?(fragment.code)
|
13
|
+
print "skip writing for redirect"
|
14
|
+
elsif fragment.code == 200
|
15
|
+
print "."
|
16
|
+
file.write(fragment)
|
17
|
+
else
|
18
|
+
raise StandardError, "Non-success status code while streaming #{fragment.code}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
puts
|
23
|
+
|
24
|
+
pp "Success: #{response.success?}"
|
25
|
+
pp File.stat(filename).inspect
|
26
|
+
File.unlink(filename)
|
data/examples/tripit_sign_in.rb
CHANGED
@@ -3,30 +3,41 @@ require File.join(dir, 'httparty')
|
|
3
3
|
|
4
4
|
class TripIt
|
5
5
|
include HTTParty
|
6
|
-
base_uri '
|
6
|
+
base_uri 'https://www.tripit.com'
|
7
7
|
debug_output
|
8
8
|
|
9
9
|
def initialize(email, password)
|
10
10
|
@email = email
|
11
|
-
|
12
|
-
|
11
|
+
get_response = self.class.get('/account/login')
|
12
|
+
get_response_cookie = parse_cookie(get_response.headers['Set-Cookie'])
|
13
|
+
|
14
|
+
post_response = self.class.post(
|
13
15
|
'/account/login',
|
14
16
|
body: {
|
15
17
|
login_email_address: email,
|
16
18
|
login_password: password
|
17
19
|
},
|
18
|
-
headers: {'Cookie' =>
|
20
|
+
headers: {'Cookie' => get_response_cookie.to_cookie_string }
|
19
21
|
)
|
20
|
-
|
22
|
+
|
23
|
+
@cookie = parse_cookie(post_response.headers['Set-Cookie'])
|
21
24
|
end
|
22
25
|
|
23
26
|
def account_settings
|
24
|
-
self.class.get('/account/edit', headers: {'Cookie' => @cookie})
|
27
|
+
self.class.get('/account/edit', headers: { 'Cookie' => @cookie.to_cookie_string })
|
25
28
|
end
|
26
29
|
|
27
30
|
def logged_in?
|
28
31
|
account_settings.include? "You're logged in as #{@email}"
|
29
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def parse_cookie(resp)
|
37
|
+
cookie_hash = CookieHash.new
|
38
|
+
resp.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
|
39
|
+
cookie_hash
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
43
|
tripit = TripIt.new('email', 'password')
|
data/examples/twitter.rb
CHANGED
@@ -14,12 +14,12 @@ class Twitter
|
|
14
14
|
# which can be :friends, :user or :public
|
15
15
|
# options[:query] can be things like since, since_id, count, etc.
|
16
16
|
def timeline(which = :friends, options = {})
|
17
|
-
options.merge!({basic_auth: @auth})
|
17
|
+
options.merge!({ basic_auth: @auth })
|
18
18
|
self.class.get("/statuses/#{which}_timeline.json", options)
|
19
19
|
end
|
20
20
|
|
21
21
|
def post(text)
|
22
|
-
options = { query: {status: text}, basic_auth: @auth }
|
22
|
+
options = { query: { status: text }, basic_auth: @auth }
|
23
23
|
self.class.post('/statuses/update.json', options)
|
24
24
|
end
|
25
25
|
end
|
data/examples/whoismyrep.rb
CHANGED
data/httparty.gemspec
CHANGED
@@ -9,20 +9,22 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.licenses = ['MIT']
|
10
10
|
s.authors = ["John Nunemaker", "Sandro Turriate"]
|
11
11
|
s.email = ["nunemaker@gmail.com"]
|
12
|
-
s.homepage = "
|
12
|
+
s.homepage = "https://github.com/jnunemaker/httparty"
|
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 = '>=
|
16
|
+
s.required_ruby_version = '>= 2.3.0'
|
17
17
|
|
18
|
-
s.add_dependency 'json', "~> 1.8"
|
19
18
|
s.add_dependency 'multi_xml', ">= 0.5.2"
|
19
|
+
s.add_dependency('mime-types', "~> 3.0")
|
20
20
|
|
21
21
|
# If this line is removed, all hard partying will cease.
|
22
22
|
s.post_install_message = "When you HTTParty, you must party hard!"
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
all_files = `git ls-files`.split("\n")
|
25
|
+
test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
|
27
|
+
s.files = all_files - test_files
|
26
28
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
27
29
|
s.require_paths = ["lib"]
|
28
30
|
end
|