http 4.4.1 → 5.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -2
- data/.travis.yml +4 -7
- data/.yardopts +1 -1
- data/CHANGES.md +2 -53
- data/README.md +8 -9
- data/http.gemspec +3 -10
- data/lib/http/client.rb +15 -14
- data/lib/http/connection.rb +1 -1
- data/lib/http/feature.rb +0 -1
- data/lib/http/features/auto_deflate.rb +2 -8
- data/lib/http/headers/known.rb +0 -3
- data/lib/http/options.rb +1 -1
- data/lib/http/redirector.rb +1 -2
- data/lib/http/request.rb +23 -26
- data/lib/http/request/body.rb +1 -25
- data/lib/http/response/parser.rb +6 -20
- data/lib/http/uri.rb +0 -13
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/client_spec.rb +7 -34
- data/spec/lib/http/redirector_spec.rb +0 -13
- data/spec/lib/http/request/body_spec.rb +0 -22
- data/spec/lib/http_spec.rb +0 -20
- data/spec/support/dummy_server/servlet.rb +0 -5
- metadata +18 -25
- data/lib/http/features/normalize_uri.rb +0 -17
- data/spec/lib/http/response/parser_spec.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2825a470cfdf9fd2d231cfe42a5d9aa54286a5cd13e402a5988f9ebfccd5fea9
|
4
|
+
data.tar.gz: ae9fbde0feda802b51bdb9926179d5c449d8ef9694d2c131eaf3226899236a7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7734a21527150dcf3e987d37c815930470e7a2620ceee1177b0885e6a23c10a571b040e16d1b2c6153c6a35c8e54aa89be1737a7e3d00c9e306caf33e4d199a2
|
7
|
+
data.tar.gz: 1ce3516a9928a62f852d3e995686a44c9ad1cd837e63c4862d7680a70b3d435b05f153f8a602f6f555dfadb431bd6567649512e596e56f54ba5c19fa040408ff
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -6,7 +6,7 @@ cache: bundler
|
|
6
6
|
before_install:
|
7
7
|
- gem update --system
|
8
8
|
- gem --version
|
9
|
-
- gem install bundler
|
9
|
+
- gem install bundler
|
10
10
|
- bundle --version
|
11
11
|
|
12
12
|
install: bundle install --without development doc
|
@@ -17,23 +17,20 @@ env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
|
17
17
|
|
18
18
|
rvm:
|
19
19
|
# Include JRuby first because it takes the longest
|
20
|
-
- jruby-9.
|
20
|
+
- jruby-9.1.16.0
|
21
21
|
- 2.3
|
22
22
|
- 2.4
|
23
23
|
- 2.5
|
24
|
-
- 2.6
|
25
|
-
- 2.7
|
26
24
|
|
27
25
|
matrix:
|
28
26
|
fast_finish: true
|
29
27
|
include:
|
30
28
|
# Only run RuboCop and Yardstick metrics on the latest Ruby
|
31
|
-
- rvm: 2.
|
29
|
+
- rvm: 2.5
|
32
30
|
env: SUITE="rubocop"
|
33
|
-
- rvm: 2.
|
31
|
+
- rvm: 2.5
|
34
32
|
env: SUITE="yardstick"
|
35
33
|
|
36
34
|
branches:
|
37
35
|
only:
|
38
36
|
- master
|
39
|
-
- 4-x-stable
|
data/.yardopts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--markup-provider=
|
1
|
+
--markup-provider=kramdown
|
2
2
|
--markup=markdown
|
data/CHANGES.md
CHANGED
@@ -1,60 +1,10 @@
|
|
1
|
-
##
|
1
|
+
## future is unwritten (master)
|
2
2
|
|
3
|
-
*
|
4
|
-
Fix parser failing on some edge cases.
|
5
|
-
([@ixti])
|
6
|
-
|
7
|
-
## 4.4.0 (2020-03-25)
|
8
|
-
|
9
|
-
* Backport [#587](https://github.com/httprb/http/pull/587)
|
10
|
-
Fix redirections when server responds with multiple Location headers.
|
11
|
-
([@ixti])
|
12
|
-
|
13
|
-
* Backport [#599](https://github.com/httprb/http/pull/599)
|
14
|
-
Allow passing HTTP::FormData::{Multipart,UrlEncoded} object directly.
|
15
|
-
([@ixti])
|
16
|
-
|
17
|
-
## 4.3.0 (2020-01-09)
|
18
|
-
|
19
|
-
* Backport [#581](https://github.com/httprb/http/pull/581)
|
20
|
-
Add Ruby-2.7 compatibility.
|
21
|
-
([@ixti], [@janko])
|
22
|
-
|
23
|
-
|
24
|
-
## 4.2.0 (2019-10-22)
|
25
|
-
|
26
|
-
* Backport [#489](https://github.com/httprb/http/pull/489)
|
3
|
+
* [#489](https://github.com/httprb/http/pull/489)
|
27
4
|
Fix HTTP parser.
|
28
5
|
([@ixti], [@fxposter])
|
29
6
|
|
30
7
|
|
31
|
-
## 4.1.1 (2019-03-12)
|
32
|
-
|
33
|
-
* Add `HTTP::Headers::ACCEPT_ENCODING` constant.
|
34
|
-
([@ixti])
|
35
|
-
|
36
|
-
|
37
|
-
## 4.1.0 (2019-03-11)
|
38
|
-
|
39
|
-
* [#533](https://github.com/httprb/http/pull/533)
|
40
|
-
Add URI normalizer feature that allows to swap default URI normalizer.
|
41
|
-
([@mamoonraja])
|
42
|
-
|
43
|
-
|
44
|
-
## 4.0.5 (2019-02-15)
|
45
|
-
|
46
|
-
* Backport [#532](https://github.com/httprb/http/pull/532) from master.
|
47
|
-
Fix pipes support in request bodies.
|
48
|
-
([@ixti])
|
49
|
-
|
50
|
-
|
51
|
-
## 4.0.4 (2019-02-12)
|
52
|
-
|
53
|
-
* Backport [#506](https://github.com/httprb/http/pull/506) from master.
|
54
|
-
Skip auto-deflate when there is no body.
|
55
|
-
([@Bonias])
|
56
|
-
|
57
|
-
|
58
8
|
## 4.0.3 (2019-01-18)
|
59
9
|
|
60
10
|
* Fix missing URL in response wrapped by auto inflate.
|
@@ -802,4 +752,3 @@ end
|
|
802
752
|
[@paul]: https://github.com/paul
|
803
753
|
[@RickCSong]: https://github.com/RickCSong
|
804
754
|
[@fxposter]: https://github.com/fxposter
|
805
|
-
[@mamoonraja]: https://github.com/mamoonraja
|
data/README.md
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# ![http.rb](https://raw.github.com/httprb/http.rb/master/logo.png)
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/http.svg)](https://rubygems.org/gems/http)
|
4
|
-
[![Build Status](https://secure.travis-ci.org/httprb/http.svg?branch=
|
5
|
-
[![Code Climate](https://codeclimate.com/github/httprb/http.svg?branch=
|
6
|
-
[![Coverage Status](https://coveralls.io/repos/httprb/http/badge.svg?branch=
|
7
|
-
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/
|
4
|
+
[![Build Status](https://secure.travis-ci.org/httprb/http.svg?branch=master)](https://travis-ci.org/httprb/http)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/httprb/http.svg?branch=master)](https://codeclimate.com/github/httprb/http)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/httprb/http/badge.svg?branch=master)](https://coveralls.io/r/httprb/http)
|
7
|
+
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/master/LICENSE.txt)
|
8
8
|
|
9
9
|
[Documentation]
|
10
10
|
|
11
|
-
_NOTE: This is the
|
11
|
+
_NOTE: This is the 5.x **development** branch. For the 4.x **stable** branch, please see:_
|
12
12
|
|
13
|
-
https://github.com/httprb/http/tree/
|
13
|
+
https://github.com/httprb/http/tree/4-x-stable
|
14
14
|
|
15
15
|
## About
|
16
16
|
|
@@ -167,8 +167,7 @@ versions:
|
|
167
167
|
* Ruby 2.3.x
|
168
168
|
* Ruby 2.4.x
|
169
169
|
* Ruby 2.5.x
|
170
|
-
*
|
171
|
-
* JRuby 9.2.x.x
|
170
|
+
* JRuby 9.1.x.x
|
172
171
|
|
173
172
|
If something doesn't work on one of these versions, it's a bug.
|
174
173
|
|
@@ -198,5 +197,5 @@ dropped.
|
|
198
197
|
|
199
198
|
## Copyright
|
200
199
|
|
201
|
-
Copyright (c) 2011-
|
200
|
+
Copyright (c) 2011-2018 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
|
202
201
|
See LICENSE.txt for further details.
|
data/http.gemspec
CHANGED
@@ -27,17 +27,10 @@ Gem::Specification.new do |gem|
|
|
27
27
|
|
28
28
|
gem.required_ruby_version = ">= 2.3"
|
29
29
|
|
30
|
-
gem.add_runtime_dependency "addressable", "~> 2.3"
|
31
|
-
gem.add_runtime_dependency "http-cookie", "~> 1.0"
|
32
|
-
gem.add_runtime_dependency "http-form_data", "~> 2.2"
|
33
30
|
gem.add_runtime_dependency "http-parser", "~> 1.2.0"
|
31
|
+
gem.add_runtime_dependency "http-form_data", "~> 2.0"
|
32
|
+
gem.add_runtime_dependency "http-cookie", "~> 1.0"
|
33
|
+
gem.add_runtime_dependency "addressable", "~> 2.3"
|
34
34
|
|
35
35
|
gem.add_development_dependency "bundler", "~> 2.0"
|
36
|
-
|
37
|
-
gem.metadata = {
|
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
|
-
}
|
43
36
|
end
|
data/lib/http/client.rb
CHANGED
@@ -42,14 +42,14 @@ module HTTP
|
|
42
42
|
uri = make_request_uri(uri, opts)
|
43
43
|
headers = make_request_headers(opts)
|
44
44
|
body = make_request_body(opts, headers)
|
45
|
+
proxy = opts.proxy
|
45
46
|
|
46
47
|
req = HTTP::Request.new(
|
47
|
-
:verb
|
48
|
-
:uri
|
49
|
-
:
|
50
|
-
:proxy
|
51
|
-
:
|
52
|
-
:body => body
|
48
|
+
:verb => verb,
|
49
|
+
:uri => uri,
|
50
|
+
:headers => headers,
|
51
|
+
:proxy => proxy,
|
52
|
+
:body => body
|
53
53
|
)
|
54
54
|
|
55
55
|
opts.features.inject(req) do |request, (_name, feature)|
|
@@ -160,6 +160,14 @@ module HTTP
|
|
160
160
|
headers[Headers::COOKIE] = cookies
|
161
161
|
end
|
162
162
|
|
163
|
+
if (auto_deflate = opts.feature(:auto_deflate))
|
164
|
+
# We need to delete Content-Length header. It will be set automatically
|
165
|
+
# by HTTP::Request::Writer
|
166
|
+
headers.delete(Headers::CONTENT_LENGTH)
|
167
|
+
|
168
|
+
headers[Headers::CONTENT_ENCODING] = auto_deflate.method
|
169
|
+
end
|
170
|
+
|
163
171
|
headers
|
164
172
|
end
|
165
173
|
|
@@ -169,7 +177,7 @@ module HTTP
|
|
169
177
|
when opts.body
|
170
178
|
opts.body
|
171
179
|
when opts.form
|
172
|
-
form =
|
180
|
+
form = HTTP::FormData.create opts.form
|
173
181
|
headers[Headers::CONTENT_TYPE] ||= form.content_type
|
174
182
|
form
|
175
183
|
when opts.json
|
@@ -178,12 +186,5 @@ module HTTP
|
|
178
186
|
body
|
179
187
|
end
|
180
188
|
end
|
181
|
-
|
182
|
-
def make_form_data(form)
|
183
|
-
return form if form.is_a? HTTP::FormData::Multipart
|
184
|
-
return form if form.is_a? HTTP::FormData::Urlencoded
|
185
|
-
|
186
|
-
HTTP::FormData.create(form)
|
187
|
-
end
|
188
189
|
end
|
189
190
|
end
|
data/lib/http/connection.rb
CHANGED
data/lib/http/feature.rb
CHANGED
@@ -10,7 +10,7 @@ module HTTP
|
|
10
10
|
class AutoDeflate < Feature
|
11
11
|
attr_reader :method
|
12
12
|
|
13
|
-
def initialize(
|
13
|
+
def initialize(*)
|
14
14
|
super
|
15
15
|
|
16
16
|
@method = @opts.key?(:method) ? @opts[:method].to_s : "gzip"
|
@@ -20,11 +20,6 @@ module HTTP
|
|
20
20
|
|
21
21
|
def wrap_request(request)
|
22
22
|
return request unless method
|
23
|
-
return request if request.body.size.zero?
|
24
|
-
|
25
|
-
# We need to delete Content-Length header. It will be set automatically by HTTP::Request::Writer
|
26
|
-
request.headers.delete(Headers::CONTENT_LENGTH)
|
27
|
-
request.headers[Headers::CONTENT_ENCODING] = method
|
28
23
|
|
29
24
|
Request.new(
|
30
25
|
:version => request.version,
|
@@ -32,8 +27,7 @@ module HTTP
|
|
32
27
|
:uri => request.uri,
|
33
28
|
:headers => request.headers,
|
34
29
|
:proxy => request.proxy,
|
35
|
-
:body => deflated_body(request.body)
|
36
|
-
:uri_normalizer => request.uri_normalizer
|
30
|
+
:body => deflated_body(request.body)
|
37
31
|
)
|
38
32
|
end
|
39
33
|
|
data/lib/http/headers/known.rb
CHANGED
@@ -5,9 +5,6 @@ module HTTP
|
|
5
5
|
# Content-Types that are acceptable for the response.
|
6
6
|
ACCEPT = "Accept"
|
7
7
|
|
8
|
-
# Content-codings that are acceptable in the response.
|
9
|
-
ACCEPT_ENCODING = "Accept-Encoding"
|
10
|
-
|
11
8
|
# The age the object has been in a proxy cache in seconds.
|
12
9
|
AGE = "Age"
|
13
10
|
|
data/lib/http/options.rb
CHANGED
data/lib/http/redirector.rb
CHANGED
@@ -58,8 +58,7 @@ module HTTP
|
|
58
58
|
|
59
59
|
@response.flush
|
60
60
|
|
61
|
-
|
62
|
-
@request = redirect_to(@response.headers.get(Headers::LOCATION).inject(:+))
|
61
|
+
@request = redirect_to @response.headers[Headers::LOCATION]
|
63
62
|
@response = yield @request
|
64
63
|
end
|
65
64
|
|
data/lib/http/request.rb
CHANGED
@@ -66,8 +66,6 @@ module HTTP
|
|
66
66
|
# Scheme is normalized to be a lowercase symbol e.g. :http, :https
|
67
67
|
attr_reader :scheme
|
68
68
|
|
69
|
-
attr_reader :uri_normalizer
|
70
|
-
|
71
69
|
# "Request URI" as per RFC 2616
|
72
70
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
|
73
71
|
attr_reader :uri
|
@@ -75,25 +73,25 @@ module HTTP
|
|
75
73
|
|
76
74
|
# @option opts [String] :version
|
77
75
|
# @option opts [#to_s] :verb HTTP request method
|
78
|
-
# @option opts [#call] :uri_normalizer (HTTP::URI::NORMALIZER)
|
79
76
|
# @option opts [HTTP::URI, #to_s] :uri
|
80
77
|
# @option opts [Hash] :headers
|
81
78
|
# @option opts [Hash] :proxy
|
82
79
|
# @option opts [String, Enumerable, IO, nil] :body
|
83
80
|
def initialize(opts)
|
84
|
-
@verb
|
85
|
-
@
|
86
|
-
|
87
|
-
@uri = @uri_normalizer.call(opts.fetch(:uri))
|
81
|
+
@verb = opts.fetch(:verb).to_s.downcase.to_sym
|
82
|
+
@uri = normalize_uri(opts.fetch(:uri))
|
88
83
|
@scheme = @uri.scheme.to_s.downcase.to_sym if @uri.scheme
|
89
84
|
|
90
85
|
raise(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
|
91
86
|
raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)
|
92
87
|
|
93
88
|
@proxy = opts[:proxy] || {}
|
89
|
+
@body = (body = opts[:body]).is_a?(Request::Body) ? body : Request::Body.new(body)
|
94
90
|
@version = opts[:version] || "1.1"
|
95
|
-
@headers =
|
96
|
-
|
91
|
+
@headers = HTTP::Headers.coerce(opts[:headers] || {})
|
92
|
+
|
93
|
+
@headers[Headers::HOST] ||= default_host_header_value
|
94
|
+
@headers[Headers::USER_AGENT] ||= USER_AGENT
|
97
95
|
end
|
98
96
|
|
99
97
|
# Returns new Request with updated uri
|
@@ -102,13 +100,12 @@ module HTTP
|
|
102
100
|
headers.delete(Headers::HOST)
|
103
101
|
|
104
102
|
self.class.new(
|
105
|
-
:verb
|
106
|
-
:uri
|
107
|
-
:headers
|
108
|
-
:proxy
|
109
|
-
:body
|
110
|
-
:version
|
111
|
-
:uri_normalizer => uri_normalizer
|
103
|
+
:verb => verb,
|
104
|
+
:uri => @uri.join(uri),
|
105
|
+
:headers => headers,
|
106
|
+
:proxy => proxy,
|
107
|
+
:body => body.source,
|
108
|
+
:version => version
|
112
109
|
)
|
113
110
|
end
|
114
111
|
|
@@ -216,17 +213,17 @@ module HTTP
|
|
216
213
|
PORTS[@scheme] != port ? "#{host}:#{port}" : host
|
217
214
|
end
|
218
215
|
|
219
|
-
|
220
|
-
|
221
|
-
|
216
|
+
# @return [HTTP::URI] URI with all componentes but query being normalized.
|
217
|
+
def normalize_uri(uri)
|
218
|
+
uri = HTTP::URI.parse uri
|
222
219
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
220
|
+
HTTP::URI.new(
|
221
|
+
:scheme => uri.normalized_scheme,
|
222
|
+
:authority => uri.normalized_authority,
|
223
|
+
:path => uri.normalized_path,
|
224
|
+
:query => uri.query,
|
225
|
+
:fragment => uri.normalized_fragment
|
226
|
+
)
|
230
227
|
end
|
231
228
|
end
|
232
229
|
end
|
data/lib/http/request/body.rb
CHANGED
@@ -35,12 +35,10 @@ module HTTP
|
|
35
35
|
yield @source
|
36
36
|
elsif @source.respond_to?(:read)
|
37
37
|
IO.copy_stream(@source, ProcIO.new(block))
|
38
|
-
rewind
|
38
|
+
@source.rewind if @source.respond_to?(:rewind)
|
39
39
|
elsif @source.is_a?(Enumerable)
|
40
40
|
@source.each(&block)
|
41
41
|
end
|
42
|
-
|
43
|
-
self
|
44
42
|
end
|
45
43
|
|
46
44
|
# Request bodies are equivalent when they have the same source.
|
@@ -50,28 +48,6 @@ module HTTP
|
|
50
48
|
|
51
49
|
private
|
52
50
|
|
53
|
-
def rewind(io)
|
54
|
-
io.rewind if io.respond_to? :rewind
|
55
|
-
rescue Errno::ESPIPE, Errno::EPIPE
|
56
|
-
# Pipe IOs respond to `:rewind` but fail when you call it.
|
57
|
-
#
|
58
|
-
# Calling `IO#rewind` on a pipe, fails with *ESPIPE* on MRI,
|
59
|
-
# but *EPIPE* on jRuby.
|
60
|
-
#
|
61
|
-
# - **ESPIPE** -- "Illegal seek."
|
62
|
-
# Invalid seek operation (such as on a pipe).
|
63
|
-
#
|
64
|
-
# - **EPIPE** -- "Broken pipe."
|
65
|
-
# There is no process reading from the other end of a pipe. Every
|
66
|
-
# library function that returns this error code also generates
|
67
|
-
# a SIGPIPE signal; this signal terminates the program if not handled
|
68
|
-
# or blocked. Thus, your program will never actually see EPIPE unless
|
69
|
-
# it has handled or blocked SIGPIPE.
|
70
|
-
#
|
71
|
-
# See: https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html
|
72
|
-
nil
|
73
|
-
end
|
74
|
-
|
75
51
|
def validate_source_type!
|
76
52
|
return if @source.is_a?(String)
|
77
53
|
return if @source.respond_to?(:read)
|
data/lib/http/response/parser.rb
CHANGED
@@ -49,17 +49,14 @@ module HTTP
|
|
49
49
|
#
|
50
50
|
|
51
51
|
def on_header_field(_response, field)
|
52
|
-
|
53
|
-
@field << field
|
52
|
+
@field = field
|
54
53
|
end
|
55
54
|
|
56
55
|
def on_header_value(_response, value)
|
57
|
-
@
|
58
|
-
@field_value << value
|
56
|
+
@headers.add(@field, value) if @field
|
59
57
|
end
|
60
58
|
|
61
59
|
def on_headers_complete(_reposse)
|
62
|
-
append_header if @reading_header_value
|
63
60
|
@finished[:headers] = true
|
64
61
|
end
|
65
62
|
|
@@ -92,26 +89,15 @@ module HTTP
|
|
92
89
|
def reset
|
93
90
|
@state.reset!
|
94
91
|
|
95
|
-
@finished
|
96
|
-
@headers
|
97
|
-
@
|
98
|
-
@
|
99
|
-
@field_value = +""
|
100
|
-
@chunk = nil
|
92
|
+
@finished = Hash.new(false)
|
93
|
+
@headers = HTTP::Headers.new
|
94
|
+
@field = nil
|
95
|
+
@chunk = nil
|
101
96
|
end
|
102
97
|
|
103
98
|
def finished?
|
104
99
|
@finished[:message]
|
105
100
|
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def append_header
|
110
|
-
@headers.add(@field, @field_value)
|
111
|
-
@reading_header_value = false
|
112
|
-
@field_value = +""
|
113
|
-
@field = +""
|
114
|
-
end
|
115
101
|
end
|
116
102
|
end
|
117
103
|
end
|
data/lib/http/uri.rb
CHANGED
@@ -26,19 +26,6 @@ module HTTP
|
|
26
26
|
# @private
|
27
27
|
HTTPS_SCHEME = "https"
|
28
28
|
|
29
|
-
# @private
|
30
|
-
NORMALIZER = lambda do |uri|
|
31
|
-
uri = HTTP::URI.parse uri
|
32
|
-
|
33
|
-
HTTP::URI.new(
|
34
|
-
:scheme => uri.normalized_scheme,
|
35
|
-
:authority => uri.normalized_authority,
|
36
|
-
:path => uri.normalized_path,
|
37
|
-
:query => uri.query,
|
38
|
-
:fragment => uri.normalized_fragment
|
39
|
-
)
|
40
|
-
end
|
41
|
-
|
42
29
|
# Parse the given URI string, returning an HTTP::URI object
|
43
30
|
#
|
44
31
|
# @param [HTTP::URI, String, #to_str] uri to parse
|
data/lib/http/version.rb
CHANGED
@@ -98,8 +98,9 @@ RSpec.describe HTTP::Client do
|
|
98
98
|
end
|
99
99
|
|
100
100
|
it "works like a charm in real world" do
|
101
|
-
|
102
|
-
|
101
|
+
url = "http://git.io/jNeY"
|
102
|
+
client = HTTP.follow
|
103
|
+
expect(client.get(url).to_s).to include "support for non-ascii URIs"
|
103
104
|
end
|
104
105
|
end
|
105
106
|
end
|
@@ -189,22 +190,6 @@ RSpec.describe HTTP::Client do
|
|
189
190
|
|
190
191
|
client.get("http://example.com/", :form => {:foo => HTTP::FormData::Part.new("content")})
|
191
192
|
end
|
192
|
-
|
193
|
-
context "when passing an HTTP::FormData object directly" do
|
194
|
-
it "creates url encoded form data object" do
|
195
|
-
client = HTTP::Client.new
|
196
|
-
form_data = HTTP::FormData::Multipart.new(:foo => "bar")
|
197
|
-
|
198
|
-
allow(client).to receive(:perform)
|
199
|
-
|
200
|
-
expect(HTTP::Request).to receive(:new) do |opts|
|
201
|
-
expect(opts[:body]).to be form_data
|
202
|
-
expect(opts[:body].to_s).to match(/^Content-Disposition: form-data; name="foo"\r\n\r\nbar\r\n/m)
|
203
|
-
end
|
204
|
-
|
205
|
-
client.get("http://example.com/", :form => form_data)
|
206
|
-
end
|
207
|
-
end
|
208
193
|
end
|
209
194
|
|
210
195
|
describe "passing json" do
|
@@ -228,9 +213,9 @@ RSpec.describe HTTP::Client do
|
|
228
213
|
end
|
229
214
|
|
230
215
|
it "works like a charm in real world" do
|
231
|
-
url
|
232
|
-
|
233
|
-
expect(
|
216
|
+
url = "https://github.com/httprb/http.rb/pull/197/ö無"
|
217
|
+
client = HTTP.follow
|
218
|
+
expect(client.get(url).to_s).to include "support for non-ascii URIs"
|
234
219
|
end
|
235
220
|
end
|
236
221
|
|
@@ -249,7 +234,7 @@ RSpec.describe HTTP::Client do
|
|
249
234
|
|
250
235
|
context "when :auto_deflate was specified" do
|
251
236
|
let(:headers) { {"Content-Length" => "12"} }
|
252
|
-
let(:client) { described_class.new :headers => headers, :features => {:auto_deflate => {}}
|
237
|
+
let(:client) { described_class.new :headers => headers, :features => {:auto_deflate => {}} }
|
253
238
|
|
254
239
|
it "deletes Content-Length header" do
|
255
240
|
expect(client).to receive(:perform) do |req, _|
|
@@ -266,18 +251,6 @@ RSpec.describe HTTP::Client do
|
|
266
251
|
|
267
252
|
client.request(:get, "http://example.com/")
|
268
253
|
end
|
269
|
-
|
270
|
-
context "and there is no body" do
|
271
|
-
let(:client) { described_class.new :headers => headers, :features => {:auto_deflate => {}} }
|
272
|
-
|
273
|
-
it "doesn't set Content-Encoding header" do
|
274
|
-
expect(client).to receive(:perform) do |req, _|
|
275
|
-
expect(req.headers).not_to include "Content-Encoding"
|
276
|
-
end
|
277
|
-
|
278
|
-
client.request(:get, "http://example.com/")
|
279
|
-
end
|
280
|
-
end
|
281
254
|
end
|
282
255
|
end
|
283
256
|
|
@@ -75,19 +75,6 @@ RSpec.describe HTTP::Redirector do
|
|
75
75
|
expect(res.to_s).to eq "foo"
|
76
76
|
end
|
77
77
|
|
78
|
-
it "concatenates multiple Location headers" do
|
79
|
-
req = HTTP::Request.new :verb => :head, :uri => "http://example.com"
|
80
|
-
headers = HTTP::Headers.new
|
81
|
-
|
82
|
-
%w[http://example.com /123].each { |loc| headers.add("Location", loc) }
|
83
|
-
|
84
|
-
res = redirector.perform(req, simple_response(301, "", headers)) do |redirect|
|
85
|
-
simple_response(200, redirect.uri.to_s)
|
86
|
-
end
|
87
|
-
|
88
|
-
expect(res.to_s).to eq "http://example.com/123"
|
89
|
-
end
|
90
|
-
|
91
78
|
context "following 300 redirect" do
|
92
79
|
context "with strict mode" do
|
93
80
|
let(:options) { {:strict => true} }
|
@@ -125,28 +125,6 @@ RSpec.describe HTTP::Request::Body do
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
-
context "when body is a pipe" do
|
129
|
-
let(:ios) { IO.pipe }
|
130
|
-
let(:body) { ios[0] }
|
131
|
-
|
132
|
-
around do |example|
|
133
|
-
writer = Thread.new(ios[1]) do |io|
|
134
|
-
io << "abcdef"
|
135
|
-
io.close
|
136
|
-
end
|
137
|
-
|
138
|
-
begin
|
139
|
-
example.run
|
140
|
-
ensure
|
141
|
-
writer.join
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
it "yields chunks of content" do
|
146
|
-
expect(chunks.inject("", :+)).to eq("abcdef")
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
128
|
context "when body is an Enumerable IO" do
|
151
129
|
let(:data) { "a" * 16 * 1024 + "b" * 10 * 1024 }
|
152
130
|
let(:body) { StringIO.new data }
|
data/spec/lib/http_spec.rb
CHANGED
@@ -430,26 +430,6 @@ RSpec.describe HTTP do
|
|
430
430
|
expect(response.to_s).to eq("#{body}-deflated")
|
431
431
|
end
|
432
432
|
end
|
433
|
-
|
434
|
-
context "with :normalize_uri" do
|
435
|
-
it "normalizes URI" do
|
436
|
-
response = HTTP.get "#{dummy.endpoint}/hello world"
|
437
|
-
expect(response.to_s).to eq("hello world")
|
438
|
-
end
|
439
|
-
|
440
|
-
it "uses the custom URI Normalizer method" do
|
441
|
-
client = HTTP.use(:normalize_uri => {:normalizer => :itself.to_proc})
|
442
|
-
response = client.get("#{dummy.endpoint}/hello world")
|
443
|
-
expect(response.status).to eq(400)
|
444
|
-
end
|
445
|
-
|
446
|
-
it "uses the default URI normalizer" do
|
447
|
-
client = HTTP.use :normalize_uri
|
448
|
-
expect(HTTP::URI::NORMALIZER).to receive(:call).and_call_original
|
449
|
-
response = client.get("#{dummy.endpoint}/hello world")
|
450
|
-
expect(response.to_s).to eq("hello world")
|
451
|
-
end
|
452
|
-
end
|
453
433
|
end
|
454
434
|
|
455
435
|
it "unifies socket errors into HTTP::ConnectionError" 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:
|
4
|
+
version: 5.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
@@ -11,64 +11,64 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2019-02-04 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
17
|
+
name: http-parser
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
20
|
- - "~>"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 1.2.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.2.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name: http-
|
31
|
+
name: http-form_data
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
34
|
- - "~>"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '
|
36
|
+
version: '2.0'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - "~>"
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '2.0'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
|
-
name: http-
|
45
|
+
name: http-cookie
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
48
|
- - "~>"
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: '
|
50
|
+
version: '1.0'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
55
|
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: '
|
57
|
+
version: '1.0'
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
59
|
+
name: addressable
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
62
|
- - "~>"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version:
|
64
|
+
version: '2.3'
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
69
|
- - "~>"
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version:
|
71
|
+
version: '2.3'
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: bundler
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,7 +116,6 @@ files:
|
|
116
116
|
- lib/http/features/auto_inflate.rb
|
117
117
|
- lib/http/features/instrumentation.rb
|
118
118
|
- lib/http/features/logging.rb
|
119
|
-
- lib/http/features/normalize_uri.rb
|
120
119
|
- lib/http/headers.rb
|
121
120
|
- lib/http/headers/known.rb
|
122
121
|
- lib/http/headers/mixin.rb
|
@@ -163,7 +162,6 @@ files:
|
|
163
162
|
- spec/lib/http/request/writer_spec.rb
|
164
163
|
- spec/lib/http/request_spec.rb
|
165
164
|
- spec/lib/http/response/body_spec.rb
|
166
|
-
- spec/lib/http/response/parser_spec.rb
|
167
165
|
- spec/lib/http/response/status_spec.rb
|
168
166
|
- spec/lib/http/response_spec.rb
|
169
167
|
- spec/lib/http/uri_spec.rb
|
@@ -183,11 +181,7 @@ files:
|
|
183
181
|
homepage: https://github.com/httprb/http
|
184
182
|
licenses:
|
185
183
|
- MIT
|
186
|
-
metadata:
|
187
|
-
source_code_uri: https://github.com/httprb/http
|
188
|
-
wiki_uri: https://github.com/httprb/http/wiki
|
189
|
-
bug_tracker_uri: https://github.com/httprb/http/issues
|
190
|
-
changelog_uri: https://github.com/httprb/http/blob/v4.4.1/CHANGES.md
|
184
|
+
metadata: {}
|
191
185
|
post_install_message:
|
192
186
|
rdoc_options: []
|
193
187
|
require_paths:
|
@@ -199,11 +193,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
199
193
|
version: '2.3'
|
200
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
195
|
requirements:
|
202
|
-
- - "
|
196
|
+
- - ">"
|
203
197
|
- !ruby/object:Gem::Version
|
204
|
-
version:
|
198
|
+
version: 1.3.1
|
205
199
|
requirements: []
|
206
|
-
rubygems_version: 3.0.
|
200
|
+
rubygems_version: 3.0.1
|
207
201
|
signing_key:
|
208
202
|
specification_version: 4
|
209
203
|
summary: HTTP should be easy
|
@@ -231,7 +225,6 @@ test_files:
|
|
231
225
|
- spec/lib/http/request/writer_spec.rb
|
232
226
|
- spec/lib/http/request_spec.rb
|
233
227
|
- spec/lib/http/response/body_spec.rb
|
234
|
-
- spec/lib/http/response/parser_spec.rb
|
235
228
|
- spec/lib/http/response/status_spec.rb
|
236
229
|
- spec/lib/http/response_spec.rb
|
237
230
|
- spec/lib/http/uri_spec.rb
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "http/uri"
|
4
|
-
|
5
|
-
module HTTP
|
6
|
-
module Features
|
7
|
-
class NormalizeUri < Feature
|
8
|
-
attr_reader :normalizer
|
9
|
-
|
10
|
-
def initialize(normalizer: HTTP::URI::NORMALIZER)
|
11
|
-
@normalizer = normalizer
|
12
|
-
end
|
13
|
-
|
14
|
-
HTTP::Options.register_feature(:normalize_uri, self)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe HTTP::Response::Parser do
|
4
|
-
subject(:parser) { described_class.new }
|
5
|
-
let(:raw_response) do
|
6
|
-
"HTTP/1.1 200 OK\r\nContent-Length: 2\r\nContent-Type: application/json\r\nMy-Header: val\r\nEmpty-Header: \r\n\r\n{}"
|
7
|
-
end
|
8
|
-
let(:expected_headers) do
|
9
|
-
{
|
10
|
-
"Content-Length" => "2",
|
11
|
-
"Content-Type" => "application/json",
|
12
|
-
"My-Header" => "val",
|
13
|
-
"Empty-Header" => ""
|
14
|
-
}
|
15
|
-
end
|
16
|
-
let(:expected_body) { "{}" }
|
17
|
-
|
18
|
-
before do
|
19
|
-
parts.each { |part| subject.add(part) }
|
20
|
-
end
|
21
|
-
|
22
|
-
context "whole response in one part" do
|
23
|
-
let(:parts) { [raw_response] }
|
24
|
-
|
25
|
-
it "parses headers" do
|
26
|
-
expect(subject.headers.to_h).to eq(expected_headers)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "parses body" do
|
30
|
-
expect(subject.read(expected_body.size)).to eq(expected_body)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "response in many parts" do
|
35
|
-
let(:parts) { raw_response.split(//) }
|
36
|
-
|
37
|
-
it "parses headers" do
|
38
|
-
expect(subject.headers.to_h).to eq(expected_headers)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "parses body" do
|
42
|
-
expect(subject.read(expected_body.size)).to eq(expected_body)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|