mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Add 'set_remote_address' config option
This commit is contained in:
parent
642ca4f6cb
commit
d5914573c9
5 changed files with 77 additions and 2 deletions
|
@ -45,11 +45,18 @@ module Puma
|
|||
|
||||
@requests_served = 0
|
||||
@hijacked = false
|
||||
|
||||
@peerip = nil
|
||||
@remote_addr_header = nil
|
||||
end
|
||||
|
||||
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
|
||||
:tempfile
|
||||
|
||||
attr_writer :peerip
|
||||
|
||||
attr_accessor :remote_addr_header
|
||||
|
||||
def inspect
|
||||
"#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>"
|
||||
end
|
||||
|
@ -297,5 +304,17 @@ module Puma
|
|||
rescue StandardError
|
||||
end
|
||||
end
|
||||
|
||||
def peerip
|
||||
return @peerip if @peerip
|
||||
|
||||
if @remote_addr_header
|
||||
hdr = @env[@remote_addr_header] || LOCALHOST_ADDR
|
||||
@peerip = hdr
|
||||
return hdr
|
||||
end
|
||||
|
||||
@peerip ||= @io.peeraddr.last
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,6 +29,7 @@ module Puma
|
|||
@conf[:worker_timeout] ||= DefaultWorkerTimeout
|
||||
@conf[:worker_boot_timeout] ||= @conf[:worker_timeout]
|
||||
@conf[:worker_shutdown_timeout] ||= DefaultWorkerShutdownTimeout
|
||||
@conf[:remote_address] ||= :socket
|
||||
|
||||
@options = {}
|
||||
end
|
||||
|
|
|
@ -183,6 +183,7 @@ module Puma
|
|||
PORT_443 = "443".freeze
|
||||
LOCALHOST = "localhost".freeze
|
||||
LOCALHOST_IP = "127.0.0.1".freeze
|
||||
LOCALHOST_ADDR = "127.0.0.1:0".freeze
|
||||
|
||||
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
||||
HTTP_11 = "HTTP/1.1".freeze
|
||||
|
|
|
@ -297,5 +297,43 @@ module Puma
|
|||
def shutdown_debug(val=true)
|
||||
@options[:shutdown_debug] = val
|
||||
end
|
||||
|
||||
# Control how the remote address of the connection is set. This
|
||||
# is configurable because to calculate the true socket peer address
|
||||
# a kernel syscall is required which for very fast rack handlers
|
||||
# slows down the handling significantly.
|
||||
#
|
||||
# There are 4 possible values:
|
||||
#
|
||||
# * :socket (the default) - read the peername from the socket using the
|
||||
# syscall. This is the normal behavior.
|
||||
# * :localhost - set the remote address to "127.0.0.1"
|
||||
# * header: http_header - set the remote address to the value of the
|
||||
# provided http header. For instance:
|
||||
# `set_remote_address header: "X-Real-IP"`
|
||||
# * Any string - this allows you to hardcode remote address to any value
|
||||
# you wish. Because puma never uses this field anyway, it's
|
||||
# format is entirely in your hands.
|
||||
def set_remote_address(val=:socket)
|
||||
case val
|
||||
when :socket
|
||||
@options[:remote_address] = val
|
||||
when :localhost
|
||||
@options[:remote_address] = :value
|
||||
@options[:remote_address_value] = "127.0.0.1".freeze
|
||||
when String
|
||||
@options[:remote_address] = :value
|
||||
@options[:remote_address_value] = val
|
||||
when Hash
|
||||
if hdr = val[:header]
|
||||
@options[:remote_address] = :header
|
||||
@options[:remote_address_header] = "HTTP_" + hdr.upcase.gsub("-", "_")
|
||||
else
|
||||
raise "Invalid value for set_remote_address - #{val.inspect}"
|
||||
end
|
||||
else
|
||||
raise "Invalid value for set_remote_address - #{val}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -307,6 +307,16 @@ module Puma
|
|||
pool = @thread_pool
|
||||
queue_requests = @queue_requests
|
||||
|
||||
remote_addr_value = nil
|
||||
remote_addr_header = nil
|
||||
|
||||
case @options[:remote_address]
|
||||
when :value
|
||||
remote_addr_value = @options[:remote_address_value]
|
||||
when :header
|
||||
remote_addr_header = @options[:remote_address_header]
|
||||
end
|
||||
|
||||
while @status == :run
|
||||
begin
|
||||
ios = IO.select sockets
|
||||
|
@ -317,6 +327,12 @@ module Puma
|
|||
begin
|
||||
if io = sock.accept_nonblock
|
||||
client = Client.new io, @binder.env(sock)
|
||||
if remote_addr_value
|
||||
client.peerip = remote_addr_value
|
||||
elsif remote_addr_header
|
||||
client.remote_addr_header = remote_addr_header
|
||||
end
|
||||
|
||||
pool << client
|
||||
pool.wait_until_not_full unless queue_requests
|
||||
end
|
||||
|
@ -481,7 +497,7 @@ module Puma
|
|||
|
||||
unless env.key?(REMOTE_ADDR)
|
||||
begin
|
||||
addr = client.peeraddr.last
|
||||
addr = client.peerip
|
||||
rescue Errno::ENOTCONN
|
||||
# Client disconnects can result in an inability to get the
|
||||
# peeraddr from the socket; default to localhost.
|
||||
|
@ -513,7 +529,7 @@ module Puma
|
|||
env = req.env
|
||||
client = req.io
|
||||
|
||||
normalize_env env, client
|
||||
normalize_env env, req
|
||||
|
||||
env[PUMA_SOCKET] = client
|
||||
|
||||
|
|
Loading…
Reference in a new issue