http.rb 1.3.9 → 1.3.11
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/CHANGELOG +24 -0
- data/lib/HTTP/REDIRECT.rb +9 -0
- data/lib/HTTP/VERSION.rb +1 -1
- data/lib/HTTP/request.rb +3 -8
- data/test/HTTP/REDIRECT_test.rb +34 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4df4290326561e27192344f8c932e0e6df4474080d8f2986c89591abb87ce7b2
|
|
4
|
+
data.tar.gz: ad38951e186650e88d4ff40dc3ce646cd5932d1c779a869c0842f642e0d15c70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34cbe673b63634c80b6acdcbac2be9cd4d72687a50a4fdc3e9412d004eda92975bf72cf3699e1a65f71221519d79255232b7af22360388434cf6b874b16a33cb
|
|
7
|
+
data.tar.gz: f09778ee10dc83dfc30047965b9c5d8ca3a671c1af19c4146d2241a8a5b7675b2aff3ac3025bd49bb58b4f94428373f2a1d6cb47a4d056ac119561c9ba9ded4f
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 20261011
|
|
4
|
+
|
|
5
|
+
1.3.11: A repeated body keeps the Content-Type it was sent with.
|
|
6
|
+
|
|
7
|
+
A 307 or 308 repeats the request with its body, and form data, `HTTP.post(uri, {a: 1})`, was repeated without its Content-Type: `form_data=` sets application/x-www-form-urlencoded upon the request object rather than among the headers given, and the request repeated is a new one, made from those headers. So the server was sent `a=1` and no type to read it by. A body sent with a Content-Type among its headers, JSON or XML, kept it, which is why it went unnoticed. As old as the 307 handling: 1.3.2 does the same.
|
|
8
|
+
|
|
9
|
+
1. ~ lib/HTTP/REDIRECT.rb: + HTTP.body_headers, which adds the request object's Content-Type to the headers where they carry none of their own.
|
|
10
|
+
2. ~ HTTP.request: a 307 or 308 is followed with body_headers, and then redirect_headers, rather than redirect_headers alone.
|
|
11
|
+
3. ~ test/HTTP/REDIRECT_test.rb: + form data's Content-Type kept through a 307 and through a 308, both failing against 1.3.10, and a Content-Type given among the headers kept in preference to it, which passes either way, being a guard.
|
|
12
|
+
4. ~ HTTP::VERSION: /1.3.10/1.3.11/
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 20261011
|
|
16
|
+
|
|
17
|
+
1.3.10: A block is yielded to once, with the response.
|
|
18
|
+
|
|
19
|
+
With a block, a followed redirect yielded the final response to it, and then yielded again whatever the block had returned, since that is what the redirected request returned and it was taken for the response: a block which returned an Array was handed that Array. With no_redirect set, the block was yielded the redirect and the redirect was then followed regardless, the branch yielding without returning, so the block was yielded to three times and a request was made which had been asked not to be.
|
|
20
|
+
|
|
21
|
+
1. ~ HTTP.request: a followed redirect returns what the redirected request returns, which has already been yielded where there is a block, rather than yielding it again.
|
|
22
|
+
2. ~ HTTP.request: no_redirect is a condition of following rather than a branch of its own, so that the redirect is yielded or returned as any other response is, and not followed.
|
|
23
|
+
3. ~ test/HTTP/REDIRECT_test.rb: + one yield with the final response when a redirect is followed, and one with the redirect when no_redirect is set. Both fail against 1.3.9.
|
|
24
|
+
4. ~ HTTP::VERSION: /1.3.9/1.3.10/
|
|
25
|
+
|
|
26
|
+
|
|
3
27
|
## 20261011
|
|
4
28
|
|
|
5
29
|
1.3.9: Only a 301, 302, 303, 307, or 308 with a Location is followed.
|
data/lib/HTTP/REDIRECT.rb
CHANGED
|
@@ -29,6 +29,15 @@ module HTTP
|
|
|
29
29
|
end
|
|
30
30
|
module_function :redirect_headers
|
|
31
31
|
|
|
32
|
+
# A body repeated carries the type it was sent with, which form data sets upon the
|
|
33
|
+
# request object rather than among the headers given.
|
|
34
|
+
def body_headers(headers, request_object)
|
|
35
|
+
return headers unless request_object['content-type']
|
|
36
|
+
return headers if headers.any?{|k, v| k.downcase == 'content-type'}
|
|
37
|
+
headers.merge('Content-Type' => request_object['content-type'])
|
|
38
|
+
end
|
|
39
|
+
module_function :body_headers
|
|
40
|
+
|
|
32
41
|
def redirect_options(options, from_uri, to_uri)
|
|
33
42
|
return options if same_origin?(from_uri, to_uri)
|
|
34
43
|
options.reject{|k, v| %i{username password}.include?(k)}
|
data/lib/HTTP/VERSION.rb
CHANGED
data/lib/HTTP/request.rb
CHANGED
|
@@ -40,19 +40,14 @@ module HTTP
|
|
|
40
40
|
http.request(request_object)
|
|
41
41
|
end
|
|
42
42
|
)
|
|
43
|
-
if redirect?(response)
|
|
44
|
-
if block_given? && no_redirect
|
|
45
|
-
yield response
|
|
46
|
-
elsif no_redirect
|
|
47
|
-
return response
|
|
48
|
-
end
|
|
43
|
+
if !no_redirect && redirect?(response)
|
|
49
44
|
redirect_uri = uri.merge(response['location'])
|
|
50
45
|
onward_options = redirect_options(given_options, uri, redirect_uri)
|
|
51
46
|
if response.code =~ /^30[78]$/
|
|
52
47
|
data = METHODS::WITH_BODY.include?(request_method) ? request_object.body : {}
|
|
53
|
-
|
|
48
|
+
return send(request_method, redirect_uri.to_s, data, redirect_headers(body_headers(headers, request_object), uri, redirect_uri), onward_options, &block)
|
|
54
49
|
else
|
|
55
|
-
|
|
50
|
+
return get(redirect_uri.to_s, {}, redirect_headers(headers, uri, redirect_uri, drop_content_type: true), onward_options, &block)
|
|
56
51
|
end
|
|
57
52
|
end
|
|
58
53
|
if block_given?
|
data/test/HTTP/REDIRECT_test.rb
CHANGED
|
@@ -111,4 +111,38 @@ describe "redirect behaviour" do
|
|
|
111
111
|
_(HTTP.get(uri).code).must_equal('302')
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
|
+
|
|
115
|
+
describe "with a block" do
|
|
116
|
+
it "yields once when a redirect is followed" do
|
|
117
|
+
stub_request(:get, uri).to_return(status: 302, headers: {'location' => other_origin_uri})
|
|
118
|
+
stub_request(:get, other_origin_uri).to_return(status: 200)
|
|
119
|
+
yielded = []
|
|
120
|
+
HTTP.get(uri){|response| yielded << response.code}
|
|
121
|
+
_(yielded).must_equal(['200'])
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "yields once, with the redirect, when no_redirect is set" do
|
|
125
|
+
stub_request(:get, uri).to_return(status: 302, headers: {'location' => other_origin_uri})
|
|
126
|
+
yielded = []
|
|
127
|
+
HTTP.get(uri, {}, {}, {no_redirect: true}){|response| yielded << response.code}
|
|
128
|
+
_(yielded).must_equal(['302'])
|
|
129
|
+
assert_not_requested(:get, other_origin_uri)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "a repeated body" do
|
|
134
|
+
%w{307 308}.each do |code|
|
|
135
|
+
it "keeps the Content-Type form data was sent with via #{code}" do
|
|
136
|
+
stub_request(:post, uri).with(headers: {'Content-Type' => 'application/x-www-form-urlencoded'}).to_return(status: code.to_i, headers: {'location' => same_origin_uri})
|
|
137
|
+
stub_request(:post, same_origin_uri).with(body: 'a=1', headers: {'Content-Type' => 'application/x-www-form-urlencoded'}).to_return(status: 200)
|
|
138
|
+
_(HTTP.post(uri, {a: 1}).success?).must_equal(true)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "keeps the Content-Type it was given rather than that of form data" do
|
|
143
|
+
stub_request(:post, uri).to_return(status: 307, headers: {'location' => same_origin_uri})
|
|
144
|
+
stub_request(:post, same_origin_uri).with(body: '{"a":1}', headers: {'Content-Type' => 'application/json'}).to_return(status: 200)
|
|
145
|
+
_(HTTP.post(uri, {a: 1}, {'Content-Type' => 'application/json'}).success?).must_equal(true)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
114
148
|
end
|