1
0
Fork 0
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:
Evan Phoenix 2016-01-06 10:12:09 -08:00
parent 642ca4f6cb
commit d5914573c9
5 changed files with 77 additions and 2 deletions

View file

@ -45,11 +45,18 @@ module Puma
@requests_served = 0 @requests_served = 0
@hijacked = false @hijacked = false
@peerip = nil
@remote_addr_header = nil
end end
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked, attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
:tempfile :tempfile
attr_writer :peerip
attr_accessor :remote_addr_header
def inspect def inspect
"#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>" "#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>"
end end
@ -297,5 +304,17 @@ module Puma
rescue StandardError rescue StandardError
end end
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
end end

View file

@ -29,6 +29,7 @@ module Puma
@conf[:worker_timeout] ||= DefaultWorkerTimeout @conf[:worker_timeout] ||= DefaultWorkerTimeout
@conf[:worker_boot_timeout] ||= @conf[:worker_timeout] @conf[:worker_boot_timeout] ||= @conf[:worker_timeout]
@conf[:worker_shutdown_timeout] ||= DefaultWorkerShutdownTimeout @conf[:worker_shutdown_timeout] ||= DefaultWorkerShutdownTimeout
@conf[:remote_address] ||= :socket
@options = {} @options = {}
end end

View file

@ -183,6 +183,7 @@ module Puma
PORT_443 = "443".freeze PORT_443 = "443".freeze
LOCALHOST = "localhost".freeze LOCALHOST = "localhost".freeze
LOCALHOST_IP = "127.0.0.1".freeze LOCALHOST_IP = "127.0.0.1".freeze
LOCALHOST_ADDR = "127.0.0.1:0".freeze
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
HTTP_11 = "HTTP/1.1".freeze HTTP_11 = "HTTP/1.1".freeze

View file

@ -297,5 +297,43 @@ module Puma
def shutdown_debug(val=true) def shutdown_debug(val=true)
@options[:shutdown_debug] = val @options[:shutdown_debug] = val
end 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
end end

View file

@ -307,6 +307,16 @@ module Puma
pool = @thread_pool pool = @thread_pool
queue_requests = @queue_requests 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 while @status == :run
begin begin
ios = IO.select sockets ios = IO.select sockets
@ -317,6 +327,12 @@ module Puma
begin begin
if io = sock.accept_nonblock if io = sock.accept_nonblock
client = Client.new io, @binder.env(sock) 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 << client
pool.wait_until_not_full unless queue_requests pool.wait_until_not_full unless queue_requests
end end
@ -481,7 +497,7 @@ module Puma
unless env.key?(REMOTE_ADDR) unless env.key?(REMOTE_ADDR)
begin begin
addr = client.peeraddr.last addr = client.peerip
rescue Errno::ENOTCONN rescue Errno::ENOTCONN
# Client disconnects can result in an inability to get the # Client disconnects can result in an inability to get the
# peeraddr from the socket; default to localhost. # peeraddr from the socket; default to localhost.
@ -513,7 +529,7 @@ module Puma
env = req.env env = req.env
client = req.io client = req.io
normalize_env env, client normalize_env env, req
env[PUMA_SOCKET] = client env[PUMA_SOCKET] = client