http 5.0.2 → 5.1.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +4 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +26 -13
- data/CHANGES.md +41 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +44 -80
- data/SECURITY.md +5 -0
- data/http.gemspec +6 -5
- data/lib/http/errors.rb +3 -0
- data/lib/http/headers.rb +1 -1
- data/lib/http/redirector.rb +49 -1
- data/lib/http/request/writer.rb +1 -1
- data/lib/http/response/status.rb +1 -1
- data/lib/http/response.rb +9 -3
- data/lib/http/timeout/global.rb +9 -29
- data/lib/http/timeout/per_operation.rb +4 -25
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/client_spec.rb +2 -2
- data/spec/lib/http/redirector_spec.rb +62 -3
- data/spec/lib/http/request/body_spec.rb +3 -3
- data/spec/lib/http/response/body_spec.rb +1 -1
- data/spec/lib/http/response_spec.rb +36 -0
- data/spec/support/http_handling_shared.rb +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3826a20981b5ed6a7e5f29fd99af814a8409dea3d556d8d4f1c1faeee0060211
|
|
4
|
+
data.tar.gz: 5f1a624d39059a53df7535df9d8094ec2eb17330ce113ee5f8201f028cb08a01
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f34965016796ff2864a48d86c45a95db18a5bd118921e9f5ab653b042d53f13332d155238b1b26d28be643b6dffea6f0bf9ac20bbc71bcab05e73e7358ca9b7d
|
|
7
|
+
data.tar.gz: dfcf6ad46848750d86cb9139b7b0ab9d4ae28624bc7c0d779450f3cfbd8de11dd6ba242855fee759210ffade294743746059157cd1eab4eb69125f644653f5e5
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -16,11 +16,11 @@ jobs:
|
|
|
16
16
|
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
|
-
ruby: [ ruby-2.
|
|
19
|
+
ruby: [ ruby-2.6, ruby-2.7, ruby-3.0, ruby-3.1 ]
|
|
20
20
|
os: [ ubuntu-latest ]
|
|
21
21
|
|
|
22
22
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v3
|
|
24
24
|
|
|
25
25
|
- uses: ruby/setup-ruby@v1
|
|
26
26
|
with:
|
|
@@ -52,11 +52,11 @@ jobs:
|
|
|
52
52
|
runs-on: ubuntu-latest
|
|
53
53
|
|
|
54
54
|
steps:
|
|
55
|
-
- uses: actions/checkout@
|
|
55
|
+
- uses: actions/checkout@v3
|
|
56
56
|
|
|
57
57
|
- uses: ruby/setup-ruby@v1
|
|
58
58
|
with:
|
|
59
|
-
ruby-version: 2.
|
|
59
|
+
ruby-version: 2.6
|
|
60
60
|
bundler-cache: true
|
|
61
61
|
|
|
62
62
|
- name: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
|
-
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit
|
|
3
|
-
# on
|
|
2
|
+
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 100`
|
|
3
|
+
# on 2022-06-16 14:35:44 UTC using RuboCop version 1.30.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
+
# Configuration parameters: Include.
|
|
12
|
+
# Include: **/*.gemspec
|
|
13
|
+
Gemspec/DeprecatedAttributeAssignment:
|
|
14
|
+
Exclude:
|
|
15
|
+
- 'http.gemspec'
|
|
16
|
+
|
|
9
17
|
# Offense count: 53
|
|
10
|
-
#
|
|
18
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
11
19
|
# Configuration parameters: EnforcedStyle.
|
|
12
20
|
# SupportedStyles: leading, trailing
|
|
13
21
|
Layout/DotPosition:
|
|
@@ -22,8 +30,8 @@ Layout/DotPosition:
|
|
|
22
30
|
- 'spec/lib/http_spec.rb'
|
|
23
31
|
- 'spec/support/http_handling_shared.rb'
|
|
24
32
|
|
|
25
|
-
# Offense count:
|
|
26
|
-
#
|
|
33
|
+
# Offense count: 176
|
|
34
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
27
35
|
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
|
|
28
36
|
# SupportedStyles: space, no_space, compact
|
|
29
37
|
# SupportedStylesForEmptyBraces: space, no_space
|
|
@@ -66,7 +74,7 @@ Metrics/AbcSize:
|
|
|
66
74
|
- 'lib/http/request.rb'
|
|
67
75
|
- 'lib/http/response.rb'
|
|
68
76
|
|
|
69
|
-
# Offense count:
|
|
77
|
+
# Offense count: 69
|
|
70
78
|
# Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
71
79
|
# IgnoredMethods: refine
|
|
72
80
|
Metrics/BlockLength:
|
|
@@ -109,7 +117,7 @@ Metrics/CyclomaticComplexity:
|
|
|
109
117
|
- 'lib/http/chainable.rb'
|
|
110
118
|
- 'lib/http/client.rb'
|
|
111
119
|
|
|
112
|
-
# Offense count:
|
|
120
|
+
# Offense count: 18
|
|
113
121
|
# Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
114
122
|
Metrics/MethodLength:
|
|
115
123
|
Exclude:
|
|
@@ -132,8 +140,13 @@ Metrics/ModuleLength:
|
|
|
132
140
|
Exclude:
|
|
133
141
|
- 'lib/http/chainable.rb'
|
|
134
142
|
|
|
143
|
+
# Offense count: 1
|
|
144
|
+
Security/CompoundHash:
|
|
145
|
+
Exclude:
|
|
146
|
+
- 'lib/http/uri.rb'
|
|
147
|
+
|
|
135
148
|
# Offense count: 2
|
|
136
|
-
#
|
|
149
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
137
150
|
# Configuration parameters: EnforcedStyle.
|
|
138
151
|
# SupportedStyles: separated, grouped
|
|
139
152
|
Style/AccessorGrouping:
|
|
@@ -141,7 +154,7 @@ Style/AccessorGrouping:
|
|
|
141
154
|
- 'lib/http/request.rb'
|
|
142
155
|
|
|
143
156
|
# Offense count: 4
|
|
144
|
-
#
|
|
157
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
145
158
|
Style/EmptyCaseCondition:
|
|
146
159
|
Exclude:
|
|
147
160
|
- 'lib/http/client.rb'
|
|
@@ -150,7 +163,7 @@ Style/EmptyCaseCondition:
|
|
|
150
163
|
- 'lib/http/response/status.rb'
|
|
151
164
|
|
|
152
165
|
# Offense count: 5
|
|
153
|
-
#
|
|
166
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
154
167
|
Style/Encoding:
|
|
155
168
|
Exclude:
|
|
156
169
|
- 'spec/lib/http/client_spec.rb'
|
|
@@ -160,7 +173,7 @@ Style/Encoding:
|
|
|
160
173
|
- 'spec/support/dummy_server/servlet.rb'
|
|
161
174
|
|
|
162
175
|
# Offense count: 17
|
|
163
|
-
# Configuration parameters: SuspiciousParamNames.
|
|
176
|
+
# Configuration parameters: SuspiciousParamNames, Allowlist.
|
|
164
177
|
# SuspiciousParamNames: options, opts, args, params, parameters
|
|
165
178
|
Style/OptionHash:
|
|
166
179
|
Exclude:
|
|
@@ -183,8 +196,8 @@ Style/OptionalBooleanParameter:
|
|
|
183
196
|
- 'lib/http/uri.rb'
|
|
184
197
|
|
|
185
198
|
# Offense count: 3
|
|
186
|
-
#
|
|
187
|
-
# Configuration parameters:
|
|
199
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
200
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
|
|
188
201
|
# URISchemes: http, https
|
|
189
202
|
Layout/LineLength:
|
|
190
203
|
Exclude:
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
## 5.1.0 (2022-06-17)
|
|
2
|
+
|
|
3
|
+
* Drop ruby-2.5 support.
|
|
4
|
+
|
|
5
|
+
* [#715](https://github.com/httprb/http/pull/715)
|
|
6
|
+
Set default encoding to UTF-8 for `application/json`.
|
|
7
|
+
([@drwl])
|
|
8
|
+
|
|
9
|
+
* [#712](https://github.com/httprb/http/pull/712)
|
|
10
|
+
Recognize cookies set by redirect.
|
|
11
|
+
([@tkellogg])
|
|
12
|
+
|
|
13
|
+
* [#707](https://github.com/httprb/http/pull/707)
|
|
14
|
+
Distinguish connection timeouts.
|
|
15
|
+
([@YuLeven])
|
|
16
|
+
|
|
17
|
+
## 5.0.4 (2021-10-07)
|
|
18
|
+
|
|
19
|
+
* [#698](https://github.com/httprb/http/pull/698)
|
|
20
|
+
Fix `HTTP::Timeout::Global#connect_ssl`.
|
|
21
|
+
([@tarcieri])
|
|
22
|
+
|
|
23
|
+
## 5.0.3 (2021-10-06)
|
|
24
|
+
|
|
25
|
+
* [#695](https://github.com/httprb/http/pull/695)
|
|
26
|
+
Revert DNS resolving feature.
|
|
27
|
+
([@PhilCoggins])
|
|
28
|
+
|
|
29
|
+
* [#694](https://github.com/httprb/http/pull/694)
|
|
30
|
+
Fix cookies extraction.
|
|
31
|
+
([@flosacca])
|
|
32
|
+
|
|
1
33
|
## 5.0.2 (2021-09-10)
|
|
2
34
|
|
|
3
35
|
* [#686](https://github.com/httprb/http/pull/686)
|
|
@@ -26,7 +58,8 @@
|
|
|
26
58
|
|
|
27
59
|
* [#638](https://github.com/httprb/http/pull/638)
|
|
28
60
|
DNS failover handling.
|
|
29
|
-
([@midnight-wonderer])
|
|
61
|
+
([@midnight-wonderer])
|
|
62
|
+
|
|
30
63
|
|
|
31
64
|
## 5.0.1 (2021-06-26)
|
|
32
65
|
|
|
@@ -42,6 +75,7 @@
|
|
|
42
75
|
Bump llhttp-ffi to 0.3.0.
|
|
43
76
|
([@bryanp])
|
|
44
77
|
|
|
78
|
+
|
|
45
79
|
## 5.0.0 (2021-05-12)
|
|
46
80
|
|
|
47
81
|
* [#656](https://github.com/httprb/http/pull/656)
|
|
@@ -94,6 +128,7 @@
|
|
|
94
128
|
|
|
95
129
|
* [#576](https://github.com/httprb/http/pull/576)
|
|
96
130
|
[#524](https://github.com/httprb/http/issues/524)
|
|
131
|
+
**BREAKING CHANGE**
|
|
97
132
|
Preserve header names casing.
|
|
98
133
|
([@joshuaflanagan])
|
|
99
134
|
|
|
@@ -948,3 +983,8 @@ end
|
|
|
948
983
|
[@midnight-wonderer]: https://github.com/midnight-wonderer
|
|
949
984
|
[@schwern]: https://github.com/schwern
|
|
950
985
|
[@matheussilvasantos]: https://github.com/matheussilvasantos
|
|
986
|
+
[@PhilCoggins]: https://github.com/PhilCoggins
|
|
987
|
+
[@flosacca]: https://github.com/flosacca
|
|
988
|
+
[@YuLeven]: https://github.com/YuLeven
|
|
989
|
+
[@drwl]: https://github.com/drwl
|
|
990
|
+
[@tkellogg]: https://github.com/tkellogg
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2011-
|
|
1
|
+
Copyright (c) 2011-2022 Tony Arcieri, Erik Michaels-Ober, Alexey V. Zapparov, Zachary Anker
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
# 
|
|
2
2
|
|
|
3
|
-
[![Gem Version]
|
|
4
|
-
[![
|
|
5
|
-
[![
|
|
6
|
-
[![
|
|
3
|
+
[![Gem Version][gem-image]][gem-link]
|
|
4
|
+
[![MIT licensed][license-image]][license-link]
|
|
5
|
+
[![Build Status][build-image]][build-link]
|
|
6
|
+
[![Code Climate][codeclimate-image]][codeclimate-link]
|
|
7
7
|
|
|
8
8
|
[Documentation]
|
|
9
9
|
|
|
10
|
-
_NOTE: This is the 5.x **development** branch. For the 4.x **stable** branch, please see:_
|
|
11
|
-
|
|
12
|
-
https://github.com/httprb/http/tree/4-x-stable
|
|
13
|
-
|
|
14
10
|
## About
|
|
15
11
|
|
|
16
12
|
HTTP (The Gem! a.k.a. http.rb) is an easy-to-use client library for making requests
|
|
@@ -21,63 +17,16 @@ Under the hood, http.rb uses the [llhttp] parser, a fast HTTP parsing native ext
|
|
|
21
17
|
This library isn't just yet another wrapper around `Net::HTTP`. It implements the HTTP
|
|
22
18
|
protocol natively and outsources the parsing to native extensions.
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
[llhttp]: https://llhttp.org/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
## Another Ruby HTTP library? Why should I care?
|
|
29
|
-
|
|
30
|
-
There are a lot of HTTP libraries to choose from in the Ruby ecosystem.
|
|
31
|
-
So why would you choose this one?
|
|
20
|
+
### Why http.rb?
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
1. **Clean API**: http.rb offers an easy-to-use API that should be a
|
|
22
|
+
- **Clean API**: http.rb offers an easy-to-use API that should be a
|
|
36
23
|
breath of fresh air after using something like Net::HTTP.
|
|
37
24
|
|
|
38
|
-
|
|
25
|
+
- **Maturity**: http.rb is one of the most mature Ruby HTTP clients, supporting
|
|
39
26
|
features like persistent connections and fine-grained timeouts.
|
|
40
27
|
|
|
41
|
-
|
|
42
|
-
http.rb achieves
|
|
43
|
-
implements the HTTP protocol in Ruby instead of C:
|
|
44
|
-
|
|
45
|
-
| HTTP client | Time | Implementation |
|
|
46
|
-
|--------------------------|--------|-----------------------|
|
|
47
|
-
| curb (persistent) | 2.519 | libcurl wrapper |
|
|
48
|
-
| em-http-request | 2.731 | EM + http_parser.rb |
|
|
49
|
-
| Typhoeus | 2.851 | libcurl wrapper |
|
|
50
|
-
| StreamlyFFI (persistent) | 2.853 | libcurl wrapper |
|
|
51
|
-
| http.rb (persistent) | 2.970 | Ruby + http_parser.rb |
|
|
52
|
-
| http.rb | 3.588 | Ruby + http_parser.rb |
|
|
53
|
-
| HTTParty | 3.931 | Net::HTTP wrapper |
|
|
54
|
-
| Net::HTTP | 3.959 | Pure Ruby |
|
|
55
|
-
| Net::HTTP (persistent) | 4.043 | Pure Ruby |
|
|
56
|
-
| open-uri | 4.479 | Net::HTTP wrapper |
|
|
57
|
-
| Excon (persistent) | 4.618 | Pure Ruby |
|
|
58
|
-
| Excon | 4.701 | Pure Ruby |
|
|
59
|
-
| RestClient | 26.838 | Net::HTTP wrapper |
|
|
60
|
-
|
|
61
|
-
Benchmarks performed using excon's benchmarking tool
|
|
62
|
-
|
|
63
|
-
DISCLAIMER: Most benchmarks you find in READMEs are crap,
|
|
64
|
-
including this one. These are out-of-date. If you care about
|
|
65
|
-
performance, benchmark for yourself for your own use cases!
|
|
66
|
-
|
|
67
|
-
## Help and Discussion
|
|
68
|
-
|
|
69
|
-
If you need help or just want to talk about the http.rb,
|
|
70
|
-
visit the http.rb Google Group:
|
|
71
|
-
|
|
72
|
-
https://groups.google.com/forum/#!forum/httprb
|
|
73
|
-
|
|
74
|
-
You can join by email by sending a message to:
|
|
75
|
-
|
|
76
|
-
[httprb+subscribe@googlegroups.com](mailto:httprb+subscribe@googlegroups.com)
|
|
77
|
-
|
|
78
|
-
If you believe you've found a bug, please report it at:
|
|
79
|
-
|
|
80
|
-
https://github.com/httprb/http/issues
|
|
28
|
+
- **Performance**: using native parsers and a clean, lightweight implementation,
|
|
29
|
+
http.rb achieves high performance while implementing HTTP in Ruby instead of C.
|
|
81
30
|
|
|
82
31
|
|
|
83
32
|
## Installation
|
|
@@ -112,10 +61,9 @@ for more detailed documentation and usage notes.
|
|
|
112
61
|
|
|
113
62
|
The following API documentation is also available:
|
|
114
63
|
|
|
115
|
-
|
|
116
|
-
|
|
64
|
+
- [YARD API documentation](https://www.rubydoc.info/github/httprb/http)
|
|
65
|
+
- [Chainable module (all chainable methods)](https://www.rubydoc.info/github/httprb/http/HTTP/Chainable)
|
|
117
66
|
|
|
118
|
-
[documentation]: https://github.com/httprb/http/wiki
|
|
119
67
|
|
|
120
68
|
### Basic Usage
|
|
121
69
|
|
|
@@ -142,7 +90,7 @@ We can also obtain an `HTTP::Response::Body` object for this response:
|
|
|
142
90
|
```
|
|
143
91
|
|
|
144
92
|
The response body can be streamed with `HTTP::Response::Body#readpartial`.
|
|
145
|
-
In practice, you'll want to bind the HTTP::Response::Body to a local variable
|
|
93
|
+
In practice, you'll want to bind the `HTTP::Response::Body` to a local variable
|
|
146
94
|
and call `#readpartial` on it repeatedly until it returns `nil`:
|
|
147
95
|
|
|
148
96
|
```ruby
|
|
@@ -159,13 +107,13 @@ and call `#readpartial` on it repeatedly until it returns `nil`:
|
|
|
159
107
|
|
|
160
108
|
## Supported Ruby Versions
|
|
161
109
|
|
|
162
|
-
This library aims to support and is [tested against][
|
|
163
|
-
versions:
|
|
110
|
+
This library aims to support and is [tested against][build-link]
|
|
111
|
+
the following Ruby versions:
|
|
164
112
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
113
|
+
- Ruby 2.6
|
|
114
|
+
- Ruby 2.7
|
|
115
|
+
- Ruby 3.0
|
|
116
|
+
- JRuby 9.2
|
|
169
117
|
|
|
170
118
|
If something doesn't work on one of these versions, it's a bug.
|
|
171
119
|
|
|
@@ -180,20 +128,36 @@ patches in a timely fashion. If critical issues for a particular implementation
|
|
|
180
128
|
exist at the time of a major release, support for that Ruby version may be
|
|
181
129
|
dropped.
|
|
182
130
|
|
|
183
|
-
[travis]: http://travis-ci.org/httprb/http
|
|
184
|
-
|
|
185
131
|
|
|
186
132
|
## Contributing to http.rb
|
|
187
133
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
134
|
+
- Fork http.rb on GitHub
|
|
135
|
+
- Make your changes
|
|
136
|
+
- Ensure all tests pass (`bundle exec rake`)
|
|
137
|
+
- Send a pull request
|
|
138
|
+
- If we like them we'll merge them
|
|
139
|
+
- If we've accepted a patch, feel free to ask for commit access!
|
|
194
140
|
|
|
195
141
|
|
|
196
142
|
## Copyright
|
|
197
143
|
|
|
198
|
-
Copyright
|
|
144
|
+
Copyright © 2011-2022 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
|
|
199
145
|
See LICENSE.txt for further details.
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
[//]: # (badges)
|
|
149
|
+
|
|
150
|
+
[gem-image]: https://img.shields.io/gem/v/http?logo=ruby
|
|
151
|
+
[gem-link]: https://rubygems.org/gems/http
|
|
152
|
+
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
153
|
+
[license-link]: https://github.com/httprb/http/blob/main/LICENSE.txt
|
|
154
|
+
[build-image]: https://github.com/httprb/http/workflows/CI/badge.svg
|
|
155
|
+
[build-link]: https://github.com/httprb/http/actions/workflows/ci.yml
|
|
156
|
+
[codeclimate-image]: https://codeclimate.com/github/httprb/http.svg?branch=main
|
|
157
|
+
[codeclimate-link]: https://codeclimate.com/github/httprb/http
|
|
158
|
+
|
|
159
|
+
[//]: # (links)
|
|
160
|
+
|
|
161
|
+
[documentation]: https://github.com/httprb/http/wiki
|
|
162
|
+
[requests]: http://docs.python-requests.org/en/latest/
|
|
163
|
+
[llhttp]: https://llhttp.org/
|
data/SECURITY.md
ADDED
data/http.gemspec
CHANGED
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
|
|
|
25
25
|
gem.require_paths = ["lib"]
|
|
26
26
|
gem.version = HTTP::VERSION
|
|
27
27
|
|
|
28
|
-
gem.required_ruby_version = ">= 2.
|
|
28
|
+
gem.required_ruby_version = ">= 2.6"
|
|
29
29
|
|
|
30
30
|
gem.add_runtime_dependency "addressable", "~> 2.8"
|
|
31
31
|
gem.add_runtime_dependency "http-cookie", "~> 1.0"
|
|
@@ -35,9 +35,10 @@ Gem::Specification.new do |gem|
|
|
|
35
35
|
gem.add_development_dependency "bundler", "~> 2.0"
|
|
36
36
|
|
|
37
37
|
gem.metadata = {
|
|
38
|
-
"source_code_uri"
|
|
39
|
-
"wiki_uri"
|
|
40
|
-
"bug_tracker_uri"
|
|
41
|
-
"changelog_uri"
|
|
38
|
+
"source_code_uri" => "https://github.com/httprb/http",
|
|
39
|
+
"wiki_uri" => "https://github.com/httprb/http/wiki",
|
|
40
|
+
"bug_tracker_uri" => "https://github.com/httprb/http/issues",
|
|
41
|
+
"changelog_uri" => "https://github.com/httprb/http/blob/v#{HTTP::VERSION}/CHANGES.md",
|
|
42
|
+
"rubygems_mfa_required" => "true"
|
|
42
43
|
}
|
|
43
44
|
end
|
data/lib/http/errors.rb
CHANGED
|
@@ -19,6 +19,9 @@ module HTTP
|
|
|
19
19
|
# Generic Timeout error
|
|
20
20
|
class TimeoutError < Error; end
|
|
21
21
|
|
|
22
|
+
# Timeout when first establishing the conncetion
|
|
23
|
+
class ConnectTimeoutError < TimeoutError; end
|
|
24
|
+
|
|
22
25
|
# Header value is of unexpected format (similar to Net::HTTPHeaderSyntaxError)
|
|
23
26
|
class HeaderError < Error; end
|
|
24
27
|
end
|
data/lib/http/headers.rb
CHANGED
data/lib/http/redirector.rb
CHANGED
|
@@ -49,6 +49,8 @@ module HTTP
|
|
|
49
49
|
@request = request
|
|
50
50
|
@response = response
|
|
51
51
|
@visited = []
|
|
52
|
+
collect_cookies_from_request
|
|
53
|
+
collect_cookies_from_response
|
|
52
54
|
|
|
53
55
|
while REDIRECT_CODES.include? @response.status.code
|
|
54
56
|
@visited << "#{@request.verb} #{@request.uri}"
|
|
@@ -59,8 +61,12 @@ module HTTP
|
|
|
59
61
|
@response.flush
|
|
60
62
|
|
|
61
63
|
# XXX(ixti): using `Array#inject` to return `nil` if no Location header.
|
|
62
|
-
@request
|
|
64
|
+
@request = redirect_to(@response.headers.get(Headers::LOCATION).inject(:+))
|
|
65
|
+
unless cookie_jar.empty?
|
|
66
|
+
@request.headers.set(Headers::COOKIE, cookie_jar.cookies.map { |c| "#{c.name}=#{c.value}" }.join("; "))
|
|
67
|
+
end
|
|
63
68
|
@response = yield @request
|
|
69
|
+
collect_cookies_from_response
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
@response
|
|
@@ -68,6 +74,48 @@ module HTTP
|
|
|
68
74
|
|
|
69
75
|
private
|
|
70
76
|
|
|
77
|
+
# All known cookies. On the original request, this is only the original cookies, but after that,
|
|
78
|
+
# Set-Cookie headers can add, set or delete cookies.
|
|
79
|
+
def cookie_jar
|
|
80
|
+
# it seems that @response.cookies instance is reused between responses, so we have to "clone"
|
|
81
|
+
@cookie_jar ||= HTTP::CookieJar.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def collect_cookies_from_request
|
|
85
|
+
request_cookie_header = @request.headers["Cookie"]
|
|
86
|
+
cookies =
|
|
87
|
+
if request_cookie_header
|
|
88
|
+
HTTP::Cookie.cookie_value_to_hash(request_cookie_header)
|
|
89
|
+
else
|
|
90
|
+
{}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
cookies.each do |key, value|
|
|
94
|
+
cookie_jar.add(HTTP::Cookie.new(key, value, :path => @request.uri.path, :domain => @request.host))
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Carry cookies from one response to the next. Carrying cookies to the next response ends up
|
|
99
|
+
# carrying them to the next request as well.
|
|
100
|
+
#
|
|
101
|
+
# Note that this isn't part of the IETF standard, but all major browsers support setting cookies
|
|
102
|
+
# on redirect: https://blog.dubbelboer.com/2012/11/25/302-cookie.html
|
|
103
|
+
def collect_cookies_from_response
|
|
104
|
+
# Overwrite previous cookies
|
|
105
|
+
@response.cookies.each do |cookie|
|
|
106
|
+
if cookie.value == ""
|
|
107
|
+
cookie_jar.delete(cookie)
|
|
108
|
+
else
|
|
109
|
+
cookie_jar.add(cookie)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# I wish we could just do @response.cookes = cookie_jar
|
|
114
|
+
cookie_jar.each do |cookie|
|
|
115
|
+
@response.cookies.add(cookie)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
71
119
|
# Check if we reached max amount of redirect hops
|
|
72
120
|
# @return [Boolean]
|
|
73
121
|
def too_many_hops?
|
data/lib/http/request/writer.rb
CHANGED
|
@@ -61,7 +61,7 @@ module HTTP
|
|
|
61
61
|
def join_headers
|
|
62
62
|
# join the headers array with crlfs, stick two on the end because
|
|
63
63
|
# that ends the request header
|
|
64
|
-
@request_header.join(CRLF) + CRLF * 2
|
|
64
|
+
@request_header.join(CRLF) + (CRLF * 2)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Writes HTTP request data into the socket.
|
data/lib/http/response/status.rb
CHANGED
|
@@ -69,7 +69,7 @@ module HTTP
|
|
|
69
69
|
# SYMBOL_CODES[:im_a_teapot] # => 418
|
|
70
70
|
#
|
|
71
71
|
# @return [Hash<Symbol => Fixnum>]
|
|
72
|
-
SYMBOL_CODES = SYMBOLS.
|
|
72
|
+
SYMBOL_CODES = SYMBOLS.to_h { |k, v| [v, k] }.freeze
|
|
73
73
|
|
|
74
74
|
# @return [Fixnum] status code
|
|
75
75
|
attr_reader :code
|
data/lib/http/response.rb
CHANGED
|
@@ -53,7 +53,7 @@ module HTTP
|
|
|
53
53
|
@body = opts.fetch(:body)
|
|
54
54
|
else
|
|
55
55
|
connection = opts.fetch(:connection)
|
|
56
|
-
encoding
|
|
56
|
+
encoding = opts[:encoding] || charset || default_encoding
|
|
57
57
|
|
|
58
58
|
@body = Response::Body.new(connection, :encoding => encoding)
|
|
59
59
|
end
|
|
@@ -138,8 +138,8 @@ module HTTP
|
|
|
138
138
|
def_delegator :content_type, :charset
|
|
139
139
|
|
|
140
140
|
def cookies
|
|
141
|
-
@cookies ||= headers.each_with_object CookieJar.new do |
|
|
142
|
-
jar.parse(v, uri)
|
|
141
|
+
@cookies ||= headers.get(Headers::SET_COOKIE).each_with_object CookieJar.new do |v, jar|
|
|
142
|
+
jar.parse(v, uri)
|
|
143
143
|
end
|
|
144
144
|
end
|
|
145
145
|
|
|
@@ -168,6 +168,12 @@ module HTTP
|
|
|
168
168
|
|
|
169
169
|
private
|
|
170
170
|
|
|
171
|
+
def default_encoding
|
|
172
|
+
return Encoding::UTF_8 if mime_type == "application/json"
|
|
173
|
+
|
|
174
|
+
Encoding::BINARY
|
|
175
|
+
end
|
|
176
|
+
|
|
171
177
|
# Initialize an HTTP::Request from options.
|
|
172
178
|
#
|
|
173
179
|
# @return [HTTP::Request]
|
data/lib/http/timeout/global.rb
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "io/wait"
|
|
4
|
-
require "resolv"
|
|
5
3
|
require "timeout"
|
|
4
|
+
require "io/wait"
|
|
6
5
|
|
|
7
6
|
require "http/timeout/null"
|
|
8
7
|
|
|
@@ -13,9 +12,6 @@ module HTTP
|
|
|
13
12
|
super
|
|
14
13
|
|
|
15
14
|
@timeout = @time_left = options.fetch(:global_timeout)
|
|
16
|
-
@dns_resolver = options.fetch(:dns_resolver) do
|
|
17
|
-
::Resolv.method(:getaddresses)
|
|
18
|
-
end
|
|
19
15
|
end
|
|
20
16
|
|
|
21
17
|
# To future me: Don't remove this again, past you was smarter.
|
|
@@ -23,28 +19,14 @@ module HTTP
|
|
|
23
19
|
@time_left = @timeout
|
|
24
20
|
end
|
|
25
21
|
|
|
26
|
-
def connect(socket_class,
|
|
27
|
-
connect_operation = lambda do |host_address|
|
|
28
|
-
::Timeout.timeout(@time_left, TimeoutError) do
|
|
29
|
-
super(socket_class, host_address, *args)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
host_addresses = @dns_resolver.call(host_name)
|
|
33
|
-
# ensure something to iterates
|
|
34
|
-
trying_targets = host_addresses.empty? ? [host_name] : host_addresses
|
|
22
|
+
def connect(socket_class, host, port, nodelay = false)
|
|
35
23
|
reset_timer
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
connect_operation.call(trying_iterator.next).tap do
|
|
40
|
-
log_time
|
|
41
|
-
end
|
|
42
|
-
rescue TimeoutError => e
|
|
43
|
-
error = e
|
|
44
|
-
retry
|
|
45
|
-
rescue ::StopIteration
|
|
46
|
-
raise error
|
|
24
|
+
::Timeout.timeout(@time_left, ConnectTimeoutError) do
|
|
25
|
+
@socket = socket_class.open(host, port)
|
|
26
|
+
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
|
|
47
27
|
end
|
|
28
|
+
|
|
29
|
+
log_time
|
|
48
30
|
end
|
|
49
31
|
|
|
50
32
|
def connect_ssl
|
|
@@ -53,12 +35,10 @@ module HTTP
|
|
|
53
35
|
begin
|
|
54
36
|
@socket.connect_nonblock
|
|
55
37
|
rescue IO::WaitReadable
|
|
56
|
-
|
|
57
|
-
log_time
|
|
38
|
+
wait_readable_or_timeout
|
|
58
39
|
retry
|
|
59
40
|
rescue IO::WaitWritable
|
|
60
|
-
|
|
61
|
-
log_time
|
|
41
|
+
wait_writable_or_timeout
|
|
62
42
|
retry
|
|
63
43
|
end
|
|
64
44
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "resolv"
|
|
4
3
|
require "timeout"
|
|
5
4
|
|
|
6
5
|
require "http/timeout/null"
|
|
@@ -18,34 +17,14 @@ module HTTP
|
|
|
18
17
|
@read_timeout = options.fetch(:read_timeout, READ_TIMEOUT)
|
|
19
18
|
@write_timeout = options.fetch(:write_timeout, WRITE_TIMEOUT)
|
|
20
19
|
@connect_timeout = options.fetch(:connect_timeout, CONNECT_TIMEOUT)
|
|
21
|
-
@dns_resolver = options.fetch(:dns_resolver) do
|
|
22
|
-
::Resolv.method(:getaddresses)
|
|
23
|
-
end
|
|
24
20
|
end
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
::Timeout.timeout(@connect_timeout, TimeoutError) do
|
|
31
|
-
super(socket_class, host_address, *args)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
host_addresses = @dns_resolver.call(host_name)
|
|
35
|
-
# ensure something to iterates
|
|
36
|
-
trying_targets = host_addresses.empty? ? [host_name] : host_addresses
|
|
37
|
-
trying_iterator = trying_targets.lazy
|
|
38
|
-
error = nil
|
|
39
|
-
begin
|
|
40
|
-
connect_operation.call(trying_iterator.next)
|
|
41
|
-
rescue TimeoutError => e
|
|
42
|
-
error = e
|
|
43
|
-
retry
|
|
44
|
-
rescue ::StopIteration
|
|
45
|
-
raise error
|
|
22
|
+
def connect(socket_class, host, port, nodelay = false)
|
|
23
|
+
::Timeout.timeout(@connect_timeout, ConnectTimeoutError) do
|
|
24
|
+
@socket = socket_class.open(host, port)
|
|
25
|
+
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
|
|
46
26
|
end
|
|
47
27
|
end
|
|
48
|
-
# rubocop:enable Metrics/MethodLength
|
|
49
28
|
|
|
50
29
|
def connect_ssl
|
|
51
30
|
rescue_readable(@connect_timeout) do
|
data/lib/http/version.rb
CHANGED
|
@@ -389,8 +389,8 @@ RSpec.describe HTTP::Client do
|
|
|
389
389
|
client.use(:test_feature => feature_instance).
|
|
390
390
|
timeout(0.001).
|
|
391
391
|
request(:post, sleep_url)
|
|
392
|
-
end.to raise_error(HTTP::
|
|
393
|
-
expect(feature_instance.captured_error).to be_a(HTTP::
|
|
392
|
+
end.to raise_error(HTTP::ConnectTimeoutError)
|
|
393
|
+
expect(feature_instance.captured_error).to be_a(HTTP::ConnectTimeoutError)
|
|
394
394
|
end
|
|
395
395
|
end
|
|
396
396
|
end
|
|
@@ -11,8 +11,12 @@ RSpec.describe HTTP::Redirector do
|
|
|
11
11
|
)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def redirect_response(status, location)
|
|
15
|
-
simple_response status, "", "Location" => location
|
|
14
|
+
def redirect_response(status, location, set_cookie = {})
|
|
15
|
+
res = simple_response status, "", "Location" => location
|
|
16
|
+
set_cookie.each do |name, value|
|
|
17
|
+
res.headers.add("Set-Cookie", "#{name}=#{value}; path=/; httponly; secure; SameSite=none; Secure")
|
|
18
|
+
end
|
|
19
|
+
res
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
describe "#strict" do
|
|
@@ -89,6 +93,61 @@ RSpec.describe HTTP::Redirector do
|
|
|
89
93
|
expect(res.to_s).to eq "http://example.com/123"
|
|
90
94
|
end
|
|
91
95
|
|
|
96
|
+
it "returns cookies in response" do
|
|
97
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
98
|
+
hops = [
|
|
99
|
+
redirect_response(301, "http://example.com/1", {"foo" => "42"}),
|
|
100
|
+
redirect_response(301, "http://example.com/2", {"bar" => "53", "deleted" => "foo"}),
|
|
101
|
+
redirect_response(301, "http://example.com/3", {"baz" => "64", "deleted" => ""}),
|
|
102
|
+
redirect_response(301, "http://example.com/4", {"baz" => "65"}),
|
|
103
|
+
simple_response(200, "bar")
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
request_cookies = [
|
|
107
|
+
{"foo" => "42"},
|
|
108
|
+
{"foo" => "42", "bar" => "53", "deleted" => "foo"},
|
|
109
|
+
{"foo" => "42", "bar" => "53", "baz" => "64"},
|
|
110
|
+
{"foo" => "42", "bar" => "53", "baz" => "65"}
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
res = redirector.perform(req, hops.shift) do |request|
|
|
114
|
+
req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
|
|
115
|
+
expect(req_cookie).to eq request_cookies.shift
|
|
116
|
+
hops.shift
|
|
117
|
+
end
|
|
118
|
+
expect(res.to_s).to eq "bar"
|
|
119
|
+
cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
|
|
120
|
+
expect(cookies["foo"]).to eq "42"
|
|
121
|
+
expect(cookies["bar"]).to eq "53"
|
|
122
|
+
expect(cookies["baz"]).to eq "65"
|
|
123
|
+
expect(cookies["deleted"]).to eq nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "returns original cookies in response" do
|
|
127
|
+
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
|
128
|
+
req.headers.set("Cookie", "foo=42; deleted=baz")
|
|
129
|
+
hops = [
|
|
130
|
+
redirect_response(301, "http://example.com/1", {"bar" => "64", "deleted" => ""}),
|
|
131
|
+
simple_response(200, "bar")
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
request_cookies = [
|
|
135
|
+
{"foo" => "42", "bar" => "64"},
|
|
136
|
+
{"foo" => "42", "bar" => "64"}
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
res = redirector.perform(req, hops.shift) do |request|
|
|
140
|
+
req_cookie = HTTP::Cookie.cookie_value_to_hash(request.headers["Cookie"] || "")
|
|
141
|
+
expect(req_cookie).to eq request_cookies.shift
|
|
142
|
+
hops.shift
|
|
143
|
+
end
|
|
144
|
+
expect(res.to_s).to eq "bar"
|
|
145
|
+
cookies = res.cookies.cookies.to_h { |c| [c.name, c.value] }
|
|
146
|
+
expect(cookies["foo"]).to eq "42"
|
|
147
|
+
expect(cookies["bar"]).to eq "64"
|
|
148
|
+
expect(cookies["deleted"]).to eq nil
|
|
149
|
+
end
|
|
150
|
+
|
|
92
151
|
context "following 300 redirect" do
|
|
93
152
|
context "with strict mode" do
|
|
94
153
|
let(:options) { {:strict => true} }
|
|
@@ -400,7 +459,7 @@ RSpec.describe HTTP::Redirector do
|
|
|
400
459
|
describe "changing verbs during redirects" do
|
|
401
460
|
let(:options) { {:strict => false} }
|
|
402
461
|
let(:post_body) { HTTP::Request::Body.new("i might be way longer in real life") }
|
|
403
|
-
let(:cookie) { "dont
|
|
462
|
+
let(:cookie) { "dont=eat my cookies" }
|
|
404
463
|
|
|
405
464
|
def a_dangerous_request(verb)
|
|
406
465
|
HTTP::Request.new(
|
|
@@ -118,10 +118,10 @@ RSpec.describe HTTP::Request::Body do
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
context "when body is a non-Enumerable IO" do
|
|
121
|
-
let(:body) { FakeIO.new("a" * 16 * 1024 + "b" * 10 * 1024) }
|
|
121
|
+
let(:body) { FakeIO.new(("a" * 16 * 1024) + ("b" * 10 * 1024)) }
|
|
122
122
|
|
|
123
123
|
it "yields chunks of content" do
|
|
124
|
-
expect(chunks.inject("", :+)).to eq "a" * 16 * 1024 + "b" * 10 * 1024
|
|
124
|
+
expect(chunks.inject("", :+)).to eq ("a" * 16 * 1024) + ("b" * 10 * 1024)
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
|
|
@@ -148,7 +148,7 @@ RSpec.describe HTTP::Request::Body do
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
context "when body is an Enumerable IO" do
|
|
151
|
-
let(:data) { "a" * 16 * 1024 + "b" * 10 * 1024 }
|
|
151
|
+
let(:data) { ("a" * 16 * 1024) + ("b" * 10 * 1024) }
|
|
152
152
|
let(:body) { StringIO.new data }
|
|
153
153
|
|
|
154
154
|
it "yields chunks of content" do
|
|
@@ -59,7 +59,7 @@ RSpec.describe HTTP::Response::Body do
|
|
|
59
59
|
let(:chunks) do
|
|
60
60
|
body = Zlib::Deflate.deflate("Hi, HTTP here ☺")
|
|
61
61
|
len = body.length
|
|
62
|
-
[body[0, len / 2], body[(len / 2)
|
|
62
|
+
[body[0, len / 2], body[(len / 2)..]]
|
|
63
63
|
end
|
|
64
64
|
subject(:body) do
|
|
65
65
|
inflater = HTTP::Response::Inflater.new(connection)
|
|
@@ -223,4 +223,40 @@ RSpec.describe HTTP::Response do
|
|
|
223
223
|
end
|
|
224
224
|
end
|
|
225
225
|
end
|
|
226
|
+
|
|
227
|
+
describe "#body" do
|
|
228
|
+
let(:connection) { double(:sequence_id => 0) }
|
|
229
|
+
let(:chunks) { ["Hello, ", "World!"] }
|
|
230
|
+
|
|
231
|
+
subject(:response) do
|
|
232
|
+
HTTP::Response.new(
|
|
233
|
+
:status => 200,
|
|
234
|
+
:version => "1.1",
|
|
235
|
+
:headers => headers,
|
|
236
|
+
:request => request,
|
|
237
|
+
:connection => connection
|
|
238
|
+
)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
before do
|
|
242
|
+
allow(connection).to receive(:readpartial) { chunks.shift }
|
|
243
|
+
allow(connection).to receive(:body_completed?) { chunks.empty? }
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context "with no Content-Type" do
|
|
247
|
+
let(:headers) { {} }
|
|
248
|
+
|
|
249
|
+
it "returns a body with default binary encoding" do
|
|
250
|
+
expect(response.body.to_s.encoding).to eq Encoding::BINARY
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
context "with Content-Type: application/json" do
|
|
255
|
+
let(:headers) { {"Content-Type" => "application/json"} }
|
|
256
|
+
|
|
257
|
+
it "returns a body with a default UTF_8 encoding" do
|
|
258
|
+
expect(response.body.to_s.encoding).to eq Encoding::UTF_8
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
226
262
|
end
|
|
@@ -77,7 +77,7 @@ RSpec.shared_context "HTTP handling" do
|
|
|
77
77
|
sleep 1.25
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
expect { response }.to raise_error(HTTP::
|
|
80
|
+
expect { response }.to raise_error(HTTP::ConnectTimeoutError, /execution/)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
it "errors if reading takes too long" do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: http
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.0
|
|
4
|
+
version: 5.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tony Arcieri
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2022-06-17 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: addressable
|
|
@@ -106,6 +106,7 @@ files:
|
|
|
106
106
|
- LICENSE.txt
|
|
107
107
|
- README.md
|
|
108
108
|
- Rakefile
|
|
109
|
+
- SECURITY.md
|
|
109
110
|
- http.gemspec
|
|
110
111
|
- lib/http.rb
|
|
111
112
|
- lib/http/chainable.rb
|
|
@@ -191,7 +192,8 @@ metadata:
|
|
|
191
192
|
source_code_uri: https://github.com/httprb/http
|
|
192
193
|
wiki_uri: https://github.com/httprb/http/wiki
|
|
193
194
|
bug_tracker_uri: https://github.com/httprb/http/issues
|
|
194
|
-
changelog_uri: https://github.com/httprb/http/blob/v5.0
|
|
195
|
+
changelog_uri: https://github.com/httprb/http/blob/v5.1.0/CHANGES.md
|
|
196
|
+
rubygems_mfa_required: 'true'
|
|
195
197
|
post_install_message:
|
|
196
198
|
rdoc_options: []
|
|
197
199
|
require_paths:
|
|
@@ -200,14 +202,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
200
202
|
requirements:
|
|
201
203
|
- - ">="
|
|
202
204
|
- !ruby/object:Gem::Version
|
|
203
|
-
version: '2.
|
|
205
|
+
version: '2.6'
|
|
204
206
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
207
|
requirements:
|
|
206
208
|
- - ">="
|
|
207
209
|
- !ruby/object:Gem::Version
|
|
208
210
|
version: '0'
|
|
209
211
|
requirements: []
|
|
210
|
-
rubygems_version: 3.
|
|
212
|
+
rubygems_version: 3.1.6
|
|
211
213
|
signing_key:
|
|
212
214
|
specification_version: 4
|
|
213
215
|
summary: HTTP should be easy
|