summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2020-02-09 12:08:22 +1300
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2020-02-09 12:10:08 +1300
commit3dda4dfd0b37ba66190330691d0bdd4566bfb2e3 (patch)
tree8026833ac360fb30bebe0b7df5d1bd04decf2847
parentc9a75ffecff48367850ddbe6aeaa3e8a001ce460 (diff)
downloadrack-request-ip.tar.gz
Rework `Request#ip` to handle empty `forwarded_for`.request-ip
-rw-r--r--lib/rack/request.rb24
-rw-r--r--test/spec_request.rb6
2 files changed, 23 insertions, 7 deletions
diff --git a/lib/rack/request.rb b/lib/rack/request.rb
index 5191c2b3..be8f0b3b 100644
--- a/lib/rack/request.rb
+++ b/lib/rack/request.rb
@@ -352,16 +352,26 @@ module Rack
end
def ip
- remote_addrs = split_header(get_header('REMOTE_ADDR'))
- remote_addrs = reject_trusted_ip_addresses(remote_addrs)
+ remote_addresses = split_header(get_header('REMOTE_ADDR'))
+ external_addresses = reject_trusted_ip_addresses(remote_addresses)
- if remote_addrs.any?
- remote_addrs.first
- else
- forwarded_ips = self.forwarded_for
+ unless external_addresses.empty?
+ return external_addresses.first
+ end
- reject_trusted_ip_addresses(forwarded_ips).last || forwarded_ips.first || get_header("REMOTE_ADDR")
+ if forwarded_for = self.forwarded_for
+ unless forwarded_for.empty?
+ # The forwarded for addresses are ordered: client, proxy1, proxy2.
+ # So we reject all the trusted addresses (proxy*) and return the
+ # last client. Or if we trust everyone, we just return the first
+ # address.
+ return reject_trusted_ip_addresses(forwarded_for).last || forwarded_for.first
+ end
end
+
+ # If all the addresses are trusted, and we aren't forwarded, just return
+ # the first remote address, which represents the source of the request.
+ remote_addresses.first
end
# The media type (type/subtype) portion of the CONTENT_TYPE header
diff --git a/test/spec_request.rb b/test/spec_request.rb
index 0d0b2f74..4e6e52d6 100644
--- a/test/spec_request.rb
+++ b/test/spec_request.rb
@@ -1270,6 +1270,12 @@ EOF
res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
res.body.must_equal '1.2.3.4'
+
+ res = mock.get '/', 'REMOTE_ADDR' => '127.0.0.1'
+ res.body.must_equal '127.0.0.1'
+
+ res = mock.get '/', 'REMOTE_ADDR' => '127.0.0.1,127.0.0.1'
+ res.body.must_equal '127.0.0.1'
end
it 'deals with proxies' do