OSDN Git Service

Replaced mongrel with thin
[redminele/redminele.git] / ruby / lib / ruby / gems / 1.8 / gems / eventmachine-0.12.10-x86-mswin32-60 / lib / em / protocols / header_and_content.rb
diff --git a/ruby/lib/ruby/gems/1.8/gems/eventmachine-0.12.10-x86-mswin32-60/lib/em/protocols/header_and_content.rb b/ruby/lib/ruby/gems/1.8/gems/eventmachine-0.12.10-x86-mswin32-60/lib/em/protocols/header_and_content.rb
new file mode 100644 (file)
index 0000000..575a4a6
--- /dev/null
@@ -0,0 +1,138 @@
+#--\r
+#\r
+# Author:: Francis Cianfrocca (gmail: blackhedd)\r
+# Homepage::  http://rubyeventmachine.com\r
+# Date:: 15 Nov 2006\r
+# \r
+# See EventMachine and EventMachine::Connection for documentation and\r
+# usage examples.\r
+#\r
+#----------------------------------------------------------------------------\r
+#\r
+# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.\r
+# Gmail: blackhedd\r
+# \r
+# This program is free software; you can redistribute it and/or modify\r
+# it under the terms of either: 1) the GNU General Public License\r
+# as published by the Free Software Foundation; either version 2 of the\r
+# License, or (at your option) any later version; or 2) Ruby's License.\r
+# \r
+# See the file COPYING for complete licensing information.\r
+#\r
+#---------------------------------------------------------------------------\r
+#\r
+#\r
+\r
+module EventMachine\r
+  module Protocols\r
+\r
+    # === Usage\r
+    #\r
+    #  class RequestHandler < EM::P::HeaderAndContentProtocol\r
+    #    def receive_request headers, content\r
+    #      p [:request, headers, content]\r
+    #    end\r
+    #  end\r
+    #\r
+    #  EM.run{\r
+    #    EM.start_server 'localhost', 80, RequestHandler\r
+    #  }\r
+    #\r
+    #--\r
+    # Originally, this subclassed LineAndTextProtocol, which in\r
+    # turn relies on BufferedTokenizer, which doesn't gracefully\r
+    # handle the transitions between lines and binary text.\r
+    # Changed 13Sep08 by FCianfrocca.\r
+    class HeaderAndContentProtocol < Connection\r
+      include LineText2\r
+\r
+      ContentLengthPattern = /Content-length:\s*(\d+)/i\r
+\r
+      def initialize *args\r
+        super\r
+        init_for_request\r
+      end\r
+\r
+      def receive_line line\r
+        case @hc_mode\r
+        when :discard_blanks\r
+          unless line == ""\r
+            @hc_mode = :headers\r
+            receive_line line\r
+          end\r
+        when :headers\r
+          if line == ""\r
+            raise "unrecognized state" unless @hc_headers.length > 0\r
+            if respond_to?(:receive_headers)\r
+              receive_headers @hc_headers\r
+            end\r
+            # @hc_content_length will be nil, not 0, if there was no content-length header.\r
+            if @hc_content_length.to_i > 0\r
+              set_binary_mode @hc_content_length\r
+            else\r
+              dispatch_request\r
+            end\r
+          else\r
+            @hc_headers << line\r
+            if ContentLengthPattern =~ line\r
+              # There are some attacks that rely on sending multiple content-length\r
+              # headers. This is a crude protection, but needs to become tunable.\r
+              raise "extraneous content-length header" if @hc_content_length\r
+              @hc_content_length = $1.to_i\r
+            end\r
+            if @hc_headers.length == 1 and respond_to?(:receive_first_header_line)\r
+              receive_first_header_line line\r
+            end\r
+          end\r
+        else\r
+          raise "internal error, unsupported mode"\r
+        end\r
+      end\r
+\r
+      def receive_binary_data text\r
+        @hc_content = text\r
+        dispatch_request\r
+      end\r
+\r
+      def dispatch_request\r
+        if respond_to?(:receive_request)\r
+          receive_request @hc_headers, @hc_content\r
+        end\r
+        init_for_request\r
+      end\r
+      private :dispatch_request\r
+\r
+      def init_for_request\r
+        @hc_mode = :discard_blanks\r
+        @hc_headers = []\r
+        # originally was @hc_headers ||= []; @hc_headers.clear to get a performance\r
+        # boost, but it's counterproductive because a subclassed handler will have to\r
+        # call dup to use the header array we pass in receive_headers.\r
+\r
+        @hc_content_length = nil\r
+        @hc_content = ""\r
+      end\r
+      private :init_for_request\r
+\r
+      # Basically a convenience method. We might create a subclass that does this\r
+      # automatically. But it's such a performance killer.\r
+      def headers_2_hash hdrs\r
+        self.class.headers_2_hash hdrs\r
+      end\r
+\r
+      class << self\r
+        def headers_2_hash hdrs\r
+          hash = {}\r
+          hdrs.each {|h|\r
+            if /\A([^\s:]+)\s*:\s*/ =~ h\r
+              tail = $'.dup\r
+              hash[ $1.downcase.gsub(/-/,"_").intern ] = tail\r
+            end\r
+          }\r
+          hash\r
+        end\r
+      end\r
+\r
+    end\r
+  end\r
+end\r