http.rb 1.3.4 → 1.3.6
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 +25 -0
- data/lib/HTTP/REDIRECT.rb +20 -0
- data/lib/HTTP/VERSION.rb +1 -1
- data/lib/HTTP/request.rb +2 -1
- data/lib/Thoran/String/Urlencode/urlencode.rb +7 -4
- data/test/HTTP/REDIRECT_test.rb +40 -0
- data/test/Thoran/String/Urlencode/urlencode_test.rb +41 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 198e221dc9a1ced43833cfa01886896755615ccc22d9773d0798627d0af1bd45
|
|
4
|
+
data.tar.gz: 53d2e227daa4558d0f810980e2b86ec60fa17c4222c2e61e507c164097c25071
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ef160053a5a5069e6be6714daf9229358ece7af8899ec0f5fcc8b98f9b5b4cb05c434d0c3a5a946f7e95a66cf55e19feb918f8096f8793b0bbc25780bd8545a
|
|
7
|
+
data.tar.gz: 0a9721b58212b93670c368496c50bc19f7ea4d53d1b860728b6a3fd5ff8b2d7f81d388cee42a6f969bd65c5ca5584d126d75e1fb5092e35372312e32593c6cd7
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 20261011
|
|
4
|
+
|
|
5
|
+
1.3.6: Authorization and Cookie headers go no further than the origin they were given to.
|
|
6
|
+
|
|
7
|
+
A 307 or 308 was followed with every header it was given, so an Authorization or Cookie header meant for one host was sent to whichever host the Location named. A 301, 302, or 303 sent no headers on at all, so it did not leak, though only because it lost everything else too. Following curl and browsers, credentials now stay with their origin: the same scheme, host, and port.
|
|
8
|
+
|
|
9
|
+
1. + lib/HTTP/REDIRECT.rb: HTTP::REDIRECT::CREDENTIAL_HEADERS (Authorization, Cookie); HTTP.same_origin?, and HTTP.redirect_headers, which drops the credential headers, whatever their case, where a redirect goes to another origin.
|
|
10
|
+
2. ~ HTTP.request: a 307 or 308 is followed with redirect_headers rather than the headers as given.
|
|
11
|
+
3. + test/HTTP/REDIRECT_test.rb: credentials kept for the same origin, and dropped for another host by 307 and by 308, for another scheme, and for another port, with other headers carried on. All but the first fail against 1.3.5.
|
|
12
|
+
4. ~ HTTP::VERSION: /1.3.5/1.3.6/
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 20261011
|
|
16
|
+
|
|
17
|
+
1.3.5: Non-ASCII is URL-encoded in full, and without a warning.
|
|
18
|
+
|
|
19
|
+
A query argument holding a multibyte character was encoded one byte per character, so only the first byte of each went out: 'Älaskår' became '%C3lask%C3r' where it should have been '%C3%84lask%C3%A5r', and a server decoding it got invalid UTF-8. The warning this was first noticed by, "historical binary regexp match /.../n against UTF-8 string", came from the same line and is only a warning, but dropping the /n alone would have left the bytes truncated, which is what kept the warning from seeming to matter.
|
|
20
|
+
|
|
21
|
+
1. ~ Thoran::String::Urlencode#urlencode: /$1.size/$1.bytesize/, so that each byte of a character is encoded rather than the first only.
|
|
22
|
+
2. ~ Thoran::String::Urlencode#urlencode: - /n flag. Matched against a UTF-8 string, a binary regexp warns on current Ruby, and the match is the same without it: a run of non-ASCII characters is still matched whole and then unpacked byte by byte, and a binary string is still matched byte-wise.
|
|
23
|
+
3. ~ Thoran/String/Urlencode/urlencode.rb: /0.4.0/0.4.1/ in the file's own header.
|
|
24
|
+
4. + test/Thoran/String/Urlencode/urlencode_test.rb: unreserved and reserved characters, a space, two and three byte characters, a binary string, the absence of a warning, and the url_encode alias. The multibyte, warning, and alias examples fail against 1.3.4.
|
|
25
|
+
5. ~ HTTP::VERSION: /1.3.4/1.3.5/
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## 20261011
|
|
4
29
|
|
|
5
30
|
1.3.4: ~ LICENSE: /2026/2009-2026/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# HTTP/REDIRECT.rb
|
|
2
|
+
# HTTP::REDIRECT (redirect helpers)
|
|
3
|
+
|
|
4
|
+
module HTTP
|
|
5
|
+
module REDIRECT
|
|
6
|
+
CREDENTIAL_HEADERS = %w{authorization cookie}.freeze
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def same_origin?(a, b)
|
|
10
|
+
[a.scheme, a.host, a.port] == [b.scheme, b.host, b.port]
|
|
11
|
+
end
|
|
12
|
+
module_function :same_origin?
|
|
13
|
+
|
|
14
|
+
# Credentials are for the origin they were given to, so they go no further than it.
|
|
15
|
+
def redirect_headers(headers, from_uri, to_uri)
|
|
16
|
+
return headers if same_origin?(from_uri, to_uri)
|
|
17
|
+
headers.reject{|k, v| REDIRECT::CREDENTIAL_HEADERS.include?(k.downcase)}
|
|
18
|
+
end
|
|
19
|
+
module_function :redirect_headers
|
|
20
|
+
end
|
data/lib/HTTP/VERSION.rb
CHANGED
data/lib/HTTP/request.rb
CHANGED
|
@@ -9,6 +9,7 @@ require_relative '../Net/HTTP/set_options'
|
|
|
9
9
|
require_relative '../Net/HTTPRequest/set_headers'
|
|
10
10
|
require_relative '../Net/HTTPResponse/StatusPredicates'
|
|
11
11
|
require_relative '../URI/Generic/use_sslQ'
|
|
12
|
+
require_relative './REDIRECT'
|
|
12
13
|
require_relative './RETRY'
|
|
13
14
|
|
|
14
15
|
module HTTP
|
|
@@ -46,7 +47,7 @@ module HTTP
|
|
|
46
47
|
redirect_uri = uri.merge(response['location'])
|
|
47
48
|
if response.code =~ /^30[78]$/
|
|
48
49
|
data = METHODS::WITH_BODY.include?(request_method) ? request_object.body : {}
|
|
49
|
-
response = send(request_method, redirect_uri.to_s, data, headers, options, &block)
|
|
50
|
+
response = send(request_method, redirect_uri.to_s, data, redirect_headers(headers, uri, redirect_uri), options, &block)
|
|
50
51
|
else
|
|
51
52
|
response = get(redirect_uri.to_s, {}, {}, options, &block)
|
|
52
53
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Thoran/String/Urlencode/urlencode.rb
|
|
2
2
|
# Thoran::String::Urlencode#urlencode
|
|
3
3
|
|
|
4
|
-
#
|
|
5
|
-
# 0.4.
|
|
4
|
+
# 20261011
|
|
5
|
+
# 0.4.1
|
|
6
6
|
|
|
7
7
|
# Acknowledgements: I've simply ripped off and refashioned the code from the CGI module!...
|
|
8
8
|
|
|
@@ -10,14 +10,17 @@
|
|
|
10
10
|
# -/0: More consistent naming.
|
|
11
11
|
# 1. /UrlEncode/Urlencode/
|
|
12
12
|
# 2. /url_encode/urlencode/
|
|
13
|
+
# 0/1: Non-ASCII is encoded in full, and without a warning.
|
|
14
|
+
# 3. /$1.size/$1.bytesize/: unpack('H2' * $1.size) took one byte per character, so only the first byte of a multibyte character was encoded and 'Älaskår' became '%C3lask%C3r'.
|
|
15
|
+
# 4. - /n flag: a binary regexp matched against a UTF-8 string warns on current Ruby (seen on 4.0.5), and the match is the same without it.
|
|
13
16
|
|
|
14
17
|
module Thoran
|
|
15
18
|
module String
|
|
16
19
|
module Urlencode
|
|
17
20
|
|
|
18
21
|
def urlencode
|
|
19
|
-
self.gsub(/([^ a-zA-Z0-9_.-]+)/
|
|
20
|
-
'%' + $1.unpack('H2' * $1.
|
|
22
|
+
self.gsub(/([^ a-zA-Z0-9_.-]+)/) do
|
|
23
|
+
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
|
21
24
|
end.tr(' ', '+')
|
|
22
25
|
end
|
|
23
26
|
alias_method :url_encode, :urlencode
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# test/HTTP/REDIRECT_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../helper'
|
|
4
|
+
|
|
5
|
+
describe "redirect behaviour" do
|
|
6
|
+
let(:uri){'http://example.com/path'}
|
|
7
|
+
let(:same_origin_uri){'http://example.com/elsewhere'}
|
|
8
|
+
let(:other_origin_uri){'http://redirected.com/path'}
|
|
9
|
+
|
|
10
|
+
describe "credentials" do
|
|
11
|
+
it "are kept for the same origin" do
|
|
12
|
+
stub_request(:get, uri).to_return(status: 307, headers: {'location' => same_origin_uri})
|
|
13
|
+
stub_request(:get, same_origin_uri).with(headers: {'Authorization' => 'Bearer x', 'Cookie' => 'session=1'}).to_return(status: 200)
|
|
14
|
+
_(HTTP.get(uri, {}, {'Authorization' => 'Bearer x', 'Cookie' => 'session=1'}).success?).must_equal(true)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
%w{307 308}.each do |code|
|
|
18
|
+
it "are dropped for another origin via #{code}" do
|
|
19
|
+
stub_request(:get, uri).to_return(status: code.to_i, headers: {'location' => other_origin_uri})
|
|
20
|
+
stub_request(:get, other_origin_uri).to_return(status: 200)
|
|
21
|
+
HTTP.get(uri, {}, {'Authorization' => 'Bearer x', 'cookie' => 'session=1', 'User-Agent' => 'Redback'})
|
|
22
|
+
assert_requested(:get, other_origin_uri){|request| !request.headers.key?('Authorization') && !request.headers.key?('Cookie') && request.headers['User-Agent'] == 'Redback'}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "are dropped for another scheme" do
|
|
27
|
+
stub_request(:get, uri).to_return(status: 307, headers: {'location' => 'https://example.com/path'})
|
|
28
|
+
stub_request(:get, 'https://example.com/path').to_return(status: 200)
|
|
29
|
+
HTTP.get(uri, {}, {'Cookie' => 'session=1'})
|
|
30
|
+
assert_requested(:get, 'https://example.com/path'){|request| !request.headers.key?('Cookie')}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "are dropped for another port" do
|
|
34
|
+
stub_request(:get, uri).to_return(status: 307, headers: {'location' => 'http://example.com:8080/path'})
|
|
35
|
+
stub_request(:get, 'http://example.com:8080/path').to_return(status: 200)
|
|
36
|
+
HTTP.get(uri, {}, {'Cookie' => 'session=1'})
|
|
37
|
+
assert_requested(:get, 'http://example.com:8080/path'){|request| !request.headers.key?('Cookie')}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# test/Thoran/String/Urlencode/urlencode_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../../../helper'
|
|
4
|
+
|
|
5
|
+
describe Thoran::String::Urlencode do
|
|
6
|
+
describe "#urlencode" do
|
|
7
|
+
it "leaves unreserved characters alone" do
|
|
8
|
+
_('aZ09_.-'.urlencode).must_equal('aZ09_.-')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "encodes a space as a plus" do
|
|
12
|
+
_('a b'.urlencode).must_equal('a+b')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "encodes reserved characters" do
|
|
16
|
+
_('a/b?c=d&e'.urlencode).must_equal('a%2Fb%3Fc%3Dd%26e')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "encodes every byte of a two byte character" do
|
|
20
|
+
_('Älaskår'.urlencode).must_equal('%C3%84lask%C3%A5r')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "encodes every byte of a three byte character" do
|
|
24
|
+
_('✓'.urlencode).must_equal('%E2%9C%93')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "encodes a binary string byte by byte" do
|
|
28
|
+
_('Ä'.b.urlencode).must_equal('%C3%84')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "does not warn on a UTF-8 string" do
|
|
32
|
+
_{'Älaskår'.urlencode}.must_be_silent
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#url_encode" do
|
|
37
|
+
it "is an alias of #urlencode" do
|
|
38
|
+
_('Ashër'.url_encode).must_equal('Ash%C3%ABr')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: http.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -95,6 +95,7 @@ files:
|
|
|
95
95
|
- http.rb.gemspec
|
|
96
96
|
- lib/HTTP.rb
|
|
97
97
|
- lib/HTTP/METHODS.rb
|
|
98
|
+
- lib/HTTP/REDIRECT.rb
|
|
98
99
|
- lib/HTTP/RETRY.rb
|
|
99
100
|
- lib/HTTP/VERSION.rb
|
|
100
101
|
- lib/HTTP/request.rb
|
|
@@ -108,6 +109,7 @@ files:
|
|
|
108
109
|
- lib/Thoran/String/Urlencode/urlencode.rb
|
|
109
110
|
- lib/URI/Generic/use_sslQ.rb
|
|
110
111
|
- test/HTTP/METHODS_test.rb
|
|
112
|
+
- test/HTTP/REDIRECT_test.rb
|
|
111
113
|
- test/HTTP/RETRY_test.rb
|
|
112
114
|
- test/HTTP/VERSION_test.rb
|
|
113
115
|
- test/HTTP/basic_auth_test.rb
|
|
@@ -122,6 +124,7 @@ files:
|
|
|
122
124
|
- test/HTTP/request_without_body_test.rb
|
|
123
125
|
- test/HTTP/trace_test.rb
|
|
124
126
|
- test/Net/HTTPResponse/StatusPredicates_test.rb
|
|
127
|
+
- test/Thoran/String/Urlencode/urlencode_test.rb
|
|
125
128
|
- test/helper.rb
|
|
126
129
|
homepage: https://github.com/thoran/http
|
|
127
130
|
licenses:
|