[前][次][番号順一覧][スレッド一覧]

ruby-changes:3475

From: ko1@a...
Date: 9 Jan 2008 20:37:27 +0900
Subject: [ruby-changes:3475] gotoyuzo - Ruby:r14968 (trunk): * lib/webrick/httprequest.rb: supprt X-Forwarded-* header fields.

gotoyuzo	2008-01-09 20:37:03 +0900 (Wed, 09 Jan 2008)

  New Revision: 14968

  Modified files:
    trunk/ChangeLog
    trunk/lib/webrick/httprequest.rb
    trunk/test/webrick/test_httprequest.rb

  Log:
    * lib/webrick/httprequest.rb: supprt X-Forwarded-* header fields.
      WEBrick::HTTPRequest#{host,port,request_uri} is derived having
      regards to X-Forwarded-Proto and X-Forwarded-Host.
    
    * lib/webrick/httprequest.rb
      (WEBrick::HTTPRequest#server_name?): new method.
      (WEBrick::HTTPRequest#remote_ip?): new method.
      (WEBrick::HTTPRequest#ssl?): new method.
    * string.c (rb_enc_cr_str_buf_cat): fix self appending.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/webrick/httprequest.rb?r1=14968&r2=14967&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=14968&r2=14967&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/webrick/test_httprequest.rb?r1=14968&r2=14967&diff_format=u

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 14967)
+++ ChangeLog	(revision 14968)
@@ -1,3 +1,14 @@
+Wed Jan  9 20:35:42 2008  GOTOU Yuuzou  <gotoyuzo@n...>
+
+	* lib/webrick/httprequest.rb: supprt X-Forwarded-* header fields.
+	  WEBrick::HTTPRequest#{host,port,request_uri} is derived having
+	  regards to X-Forwarded-Proto and X-Forwarded-Host.
+
+	* lib/webrick/httprequest.rb
+	  (WEBrick::HTTPRequest#server_name?): new method.
+	  (WEBrick::HTTPRequest#remote_ip?): new method.
+	  (WEBrick::HTTPRequest#ssl?): new method.
+
 Wed Jan  9 18:24:39 2008  WATANABE Hirofumi  <eban@r...>
 
 	* golf_prelude.rb (Array#to_s): alias to join.
Index: lib/webrick/httprequest.rb
===================================================================
--- lib/webrick/httprequest.rb	(revision 14967)
+++ lib/webrick/httprequest.rb	(revision 14968)
@@ -69,6 +69,9 @@
 
       @remaining_size = nil
       @socket = nil
+
+      @forwarded_proto = @forwarded_host = @forwarded_port =
+        @forwarded_server = @forwarded_for = nil
     end
 
     def parse(socket=nil)
@@ -95,6 +98,7 @@
       return if @unparsed_uri == "*"
 
       begin
+        setup_forwarded_info
         @request_uri = parse_uri(@unparsed_uri)
         @path = HTTPUtils::unescape(@request_uri.path)
         @path = HTTPUtils::normalize_path(@path)
@@ -153,6 +157,26 @@
       }
     end
 
+    def host
+      return @forwarded_host || @host
+    end
+
+    def port
+      return @forwarded_port || @port
+    end
+
+    def server_name
+      return @forwarded_server || @config[:ServerName]
+    end
+
+    def remote_ip
+      return self["client-ip"] || @forwarded_for || @peeraddr[3]
+    end
+
+    def ssl?
+      return @request_uri.scheme == "https"
+    end
+
     def keep_alive?
       @keep_alive
     end
@@ -255,7 +279,9 @@
       end
       uri = URI::parse(str)
       return uri if uri.absolute?
-      if self["host"]
+      if @forwarded_host
+        host, port = @forwarded_host, @forwarded_port
+      elsif self["host"]
         pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n
         host, port = *self['host'].scan(pattern)[0]
       elsif @addr.size > 0
@@ -263,7 +289,7 @@
       else
         host, port = @config[:ServerName], @config[:Port]
       end
-      uri.scheme = scheme
+      uri.scheme = @forwarded_proto || scheme
       uri.host = host
       uri.port = port ? port.to_i : nil
       return URI::parse(uri.to_s)
@@ -356,5 +382,25 @@
         raise HTTPStatus::BadRequest, ex.message
       end
     end
+
+    PrivateNetworkRegexp = /
+      ^unknown$|
+      ^((::ffff:)?127.0.0.1|::1)$|
+      ^(::ffff:)?(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.
+    /ixo
+
+    def setup_forwarded_info
+      @forwarded_server = self["x-forwarded-server"]
+      @forwarded_proto = self["x-forwarded-proto"]
+      if host_port = self["x-forwarded-host"]
+        @forwarded_host, tmp = host_port.split(":", 2)
+        @forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i
+      end
+      if addrs = self["x-forwarded-for"]
+        addrs = addrs.split(",").collect(&:strip)
+        addrs.reject!{|ip| PrivateNetworkRegexp =~ ip }
+        @forwarded_for = addrs.first
+      end
+    end
   end
 end
Index: test/webrick/test_httprequest.rb
===================================================================
--- test/webrick/test_httprequest.rb	(revision 14967)
+++ test/webrick/test_httprequest.rb	(revision 14968)
@@ -79,6 +79,7 @@
       Accept-Language: ja
       Content-Type: text/plain
       Content-Length: 7
+      X-Empty-Header: 
 
       foobar
     _end_of_message_
@@ -97,6 +98,8 @@
     assert_equal(7, req.content_length)
     assert_equal("text/plain", req.content_type)
     assert_equal("foobar\n", req.body)
+    assert_equal("", req["x-empty-header"])
+    assert_equal(nil, req["x-no-header"])
     assert(req.query.empty?)
   end
 
@@ -238,6 +241,70 @@
     assert_equal(File.read(__FILE__), req.body)
   end
 
+  def test_forwarded
+    msg = <<-_end_of_message_
+      GET /foo HTTP/1.1
+      Host: localhost:10080
+      User-Agent: w3m/0.5.2
+      X-Forwarded-For: 123.123.123.123
+      X-Forwarded-Host: forward.example.com
+      X-Forwarded-Server: server.example.com
+      Connection: Keep-Alive
+
+    _end_of_message_
+    msg.gsub!(/^ {6}/, "")
+    req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+    req.parse(StringIO.new(msg))
+    assert_equal("server.example.com", req.server_name)
+    assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
+    assert_equal("forward.example.com", req.host)
+    assert_equal(80, req.port)
+    assert_equal("123.123.123.123", req.remote_ip)
+    assert(!req.ssl?)
+
+    msg = <<-_end_of_message_
+      GET /foo HTTP/1.1
+      Host: localhost:10080
+      User-Agent: w3m/0.5.2
+      X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
+      X-Forwarded-Host: forward.example.com:8080
+      X-Forwarded-Server: server.example.com
+      Connection: Keep-Alive
+
+    _end_of_message_
+    msg.gsub!(/^ {6}/, "")
+    req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+    req.parse(StringIO.new(msg))
+    assert_equal("server.example.com", req.server_name)
+    assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
+    assert_equal("forward.example.com", req.host)
+    assert_equal(8080, req.port)
+    assert_equal("123.123.123.123", req.remote_ip)
+    assert(!req.ssl?)
+
+    msg = <<-_end_of_message_
+      GET /foo HTTP/1.1
+      Host: localhost:10080
+      Client-IP: 234.234.234.234
+      X-Forwarded-Proto: https
+      X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
+      X-Forwarded-Host: forward.example.com
+      X-Forwarded-Server: server.example.com
+      X-Requested-With: XMLHttpRequest
+      Connection: Keep-Alive
+
+    _end_of_message_
+    msg.gsub!(/^ {6}/, "")
+    req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+    req.parse(StringIO.new(msg))
+    assert_equal("server.example.com", req.server_name)
+    assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
+    assert_equal("forward.example.com", req.host)
+    assert_equal(443, req.port)
+    assert_equal("234.234.234.234", req.remote_ip)
+    assert(req.ssl?)
+  end
+
   def test_bad_messages
     param = "foo=1;foo=2;foo=3;bar=x"
     msg = <<-_end_of_message_

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧]