em-rack-mongrel2 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +7 -0
 - data/LICENSE +20 -0
 - data/README.md +67 -0
 - data/Rakefile +127 -0
 - data/em-rack-mongrel2.gemspec +84 -0
 - data/example/.gitignore +4 -0
 - data/example/async_sinatra/app.rb +14 -0
 - data/example/async_sinatra/config.ru +8 -0
 - data/example/mongrel2.conf +30 -0
 - data/example/sinatra/.gitignore +3 -0
 - data/example/sinatra/app.rb +7 -0
 - data/example/sinatra/config.ru +8 -0
 - data/lib/mongrel2/connection.rb +75 -0
 - data/lib/mongrel2/request.rb +76 -0
 - data/lib/mongrel2/response.rb +70 -0
 - data/lib/mongrel2.rb +14 -0
 - data/lib/rack/handler/mongrel2.rb +37 -0
 - data/spec/request_spec.rb +58 -0
 - data/spec/response_spec.rb +30 -0
 - data/spec/spec.opts +1 -0
 - data/spec/spec_helper.rb +3 -0
 - metadata +166 -0
 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2010, 2011 Daniel Huckstep
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 4 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 5 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 6 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 7 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 8 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 9 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 12 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 15 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 16 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 17 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 18 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 19 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 20 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # em-rack-mongrel2
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This is a Mongrel2 Rack handler that supports EventMachine and async response.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            I folked this from darkhelmet's rack-mongrel2 so that I can rack up async_sinatra apps.
         
     | 
| 
      
 6 
     | 
    
         
            +
            Tested on async_sinatra but will be able to run any Rack apps that requires an async web server such as Thin.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            This is my very first contribution to Ruby ecosystem. Let me know if I've done wrong.
         
     | 
| 
      
 9 
     | 
    
         
            +
            Pull requests and feature requests are very welcome!
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## How to run examples
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Clone the repository.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                git clone https://github.com/ichiban/em-rack-mongrel2.git
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Download all dependencies.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                cd em-rack-mongrel2
         
     | 
| 
      
 20 
     | 
    
         
            +
                bundle install
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            Run Mongrel2.
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                cd example
         
     | 
| 
      
 25 
     | 
    
         
            +
                mkdir -p tmp/pids logs
         
     | 
| 
      
 26 
     | 
    
         
            +
                m2sh load
         
     | 
| 
      
 27 
     | 
    
         
            +
                m2sh start -name main
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Run a simple sinatra example or
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                cd sinatra
         
     | 
| 
      
 32 
     | 
    
         
            +
                export RACK_MONGREL2_SEND=tcp://127.0.0.1:9996
         
     | 
| 
      
 33 
     | 
    
         
            +
                export RACK_MONGREL2_RECV=tcp://127.0.0.1:9997
         
     | 
| 
      
 34 
     | 
    
         
            +
                export RACK_MONGREL2_UUID=9539ED88-1B33-4D19-A9F9-283E5BF11AC7
         
     | 
| 
      
 35 
     | 
    
         
            +
                rackup -s Mongrel2
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            Run an async sinatra example.
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                cd async_sinatra
         
     | 
| 
      
 40 
     | 
    
         
            +
                export RACK_MONGREL2_SEND=tcp://127.0.0.1:9998
         
     | 
| 
      
 41 
     | 
    
         
            +
                export RACK_MONGREL2_RECV=tcp://127.0.0.1:9999
         
     | 
| 
      
 42 
     | 
    
         
            +
                export RACK_MONGREL2_UUID=AEE66029-E420-42E7-A7C8-6C37BBFC7B9F
         
     | 
| 
      
 43 
     | 
    
         
            +
                rackup -s Mongrel2
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ## How to use in your projects (work in progress)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            1. Get mongrel2 installed (http://mongrel2.org/wiki/quick_start.html)
         
     | 
| 
      
 48 
     | 
    
         
            +
            1. Get your config for mongrel2 setup (see example directory)
         
     | 
| 
      
 49 
     | 
    
         
            +
            1. Add it to your Gemfile (gem 'em-rack-mongrel2', '~> 0.0.0' # This is not available yet.)
         
     | 
| 
      
 50 
     | 
    
         
            +
            1. You also need some sort of JSON parsing library installed, like Yajl or JSON (gem i yajl-ruby or gem i json). json-jruby will work too
         
     | 
| 
      
 51 
     | 
    
         
            +
            1. Run Mongrel2
         
     | 
| 
      
 52 
     | 
    
         
            +
            1. Run your rack application
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ## Note on Patches/Pull Requests
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            * Fork the project.
         
     | 
| 
      
 57 
     | 
    
         
            +
            * Make your feature addition or bug fix.
         
     | 
| 
      
 58 
     | 
    
         
            +
            * Add tests for it. This is important so I don't break it in a
         
     | 
| 
      
 59 
     | 
    
         
            +
              future version unintentionally.
         
     | 
| 
      
 60 
     | 
    
         
            +
            * Commit, do not mess with rakefile, version, or history.
         
     | 
| 
      
 61 
     | 
    
         
            +
              (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
         
     | 
| 
      
 62 
     | 
    
         
            +
            * Send me a pull request. Bonus points for topic branches.
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            ## Copyright
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            * Original project Copyright (c) 2010, 2011 Daniel Huckstep. See LICENSE for details.
         
     | 
| 
      
 67 
     | 
    
         
            +
            * This derivative project Copyright (c) 2011 ICHIBANGASE, Yutaka.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,127 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'date'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            # Helper functions
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            def name
         
     | 
| 
      
 12 
     | 
    
         
            +
              @name ||= Dir['*.gemspec'].first.split('.').first
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            def version
         
     | 
| 
      
 16 
     | 
    
         
            +
              line = File.read("lib/mongrel2.rb")[/^\s*VERSION\s*=\s*.*/]
         
     | 
| 
      
 17 
     | 
    
         
            +
              line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            def date
         
     | 
| 
      
 21 
     | 
    
         
            +
              Date.today.to_s
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            def rubyforge_project
         
     | 
| 
      
 25 
     | 
    
         
            +
              name
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            def gemspec_file
         
     | 
| 
      
 29 
     | 
    
         
            +
              "#{name}.gemspec"
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            def gem_file
         
     | 
| 
      
 33 
     | 
    
         
            +
              "#{name}-#{version}.gem"
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            def replace_header(head, header_name)
         
     | 
| 
      
 37 
     | 
    
         
            +
              head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 41 
     | 
    
         
            +
            #
         
     | 
| 
      
 42 
     | 
    
         
            +
            # Standard tasks
         
     | 
| 
      
 43 
     | 
    
         
            +
            #
         
     | 
| 
      
 44 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            task :default => :spec
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 49 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:spec) do |t|
         
     | 
| 
      
 50 
     | 
    
         
            +
              t.ruby_opts = ['-Ilib', '-Ispec']
         
     | 
| 
      
 51 
     | 
    
         
            +
              t.pattern = 'spec/**/*_spec.rb'
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            desc "Open an irb session preloaded with this library"
         
     | 
| 
      
 55 
     | 
    
         
            +
            task :console do
         
     | 
| 
      
 56 
     | 
    
         
            +
              sh "irb -rubygems -r ./lib/#{name}.rb"
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 60 
     | 
    
         
            +
            #
         
     | 
| 
      
 61 
     | 
    
         
            +
            # Custom tasks (add your own tasks here)
         
     | 
| 
      
 62 
     | 
    
         
            +
            #
         
     | 
| 
      
 63 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            begin
         
     | 
| 
      
 66 
     | 
    
         
            +
              require 'yard'
         
     | 
| 
      
 67 
     | 
    
         
            +
              YARD::Rake::YardocTask.new
         
     | 
| 
      
 68 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 69 
     | 
    
         
            +
              task :yardoc do
         
     | 
| 
      
 70 
     | 
    
         
            +
                abort 'YARD is not available. In order to run yardoc, you must: `gem i yard`'
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 75 
     | 
    
         
            +
            #
         
     | 
| 
      
 76 
     | 
    
         
            +
            # Packaging tasks
         
     | 
| 
      
 77 
     | 
    
         
            +
            #
         
     | 
| 
      
 78 
     | 
    
         
            +
            #############################################################################
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
         
     | 
| 
      
 81 
     | 
    
         
            +
            task :release => :build do
         
     | 
| 
      
 82 
     | 
    
         
            +
              unless `git branch` =~ /^\* master$/
         
     | 
| 
      
 83 
     | 
    
         
            +
                puts "You must be on the master branch to release!"
         
     | 
| 
      
 84 
     | 
    
         
            +
                exit!
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
              sh "git commit --allow-empty -a -m 'Release #{version}'"
         
     | 
| 
      
 87 
     | 
    
         
            +
              sh "git tag v#{version}"
         
     | 
| 
      
 88 
     | 
    
         
            +
              sh "git push origin master"
         
     | 
| 
      
 89 
     | 
    
         
            +
              sh "git push origin v#{version}"
         
     | 
| 
      
 90 
     | 
    
         
            +
              sh "gem push pkg/#{name}-#{version}.gem"
         
     | 
| 
      
 91 
     | 
    
         
            +
            end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            desc "Build #{gem_file} into the pkg directory"
         
     | 
| 
      
 94 
     | 
    
         
            +
            task :build => :gemspec do
         
     | 
| 
      
 95 
     | 
    
         
            +
              sh "mkdir -p pkg"
         
     | 
| 
      
 96 
     | 
    
         
            +
              sh "gem build #{gemspec_file}"
         
     | 
| 
      
 97 
     | 
    
         
            +
              sh "mv #{gem_file} pkg"
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            desc "Generate #{gemspec_file}"
         
     | 
| 
      
 101 
     | 
    
         
            +
            task :gemspec do
         
     | 
| 
      
 102 
     | 
    
         
            +
              # read spec file and split out manifest section
         
     | 
| 
      
 103 
     | 
    
         
            +
              spec = File.read(gemspec_file)
         
     | 
| 
      
 104 
     | 
    
         
            +
              head, manifest, tail = spec.split("  # = MANIFEST =\n")
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
              # replace name version and date
         
     | 
| 
      
 107 
     | 
    
         
            +
              replace_header(head, :name)
         
     | 
| 
      
 108 
     | 
    
         
            +
              replace_header(head, :version)
         
     | 
| 
      
 109 
     | 
    
         
            +
              replace_header(head, :date)
         
     | 
| 
      
 110 
     | 
    
         
            +
              #comment this out if your rubyforge_project has a different name
         
     | 
| 
      
 111 
     | 
    
         
            +
              replace_header(head, :rubyforge_project)
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              # determine file list from git ls-files
         
     | 
| 
      
 114 
     | 
    
         
            +
              files = `git ls-files`.
         
     | 
| 
      
 115 
     | 
    
         
            +
                split("\n").
         
     | 
| 
      
 116 
     | 
    
         
            +
                sort.
         
     | 
| 
      
 117 
     | 
    
         
            +
                reject { |file| file =~ /^\./ }.
         
     | 
| 
      
 118 
     | 
    
         
            +
                reject { |file| file =~ /^(rdoc|pkg)/ }.
         
     | 
| 
      
 119 
     | 
    
         
            +
                map { |file| "    #{file}" }.
         
     | 
| 
      
 120 
     | 
    
         
            +
                join("\n")
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              # piece file back together and write
         
     | 
| 
      
 123 
     | 
    
         
            +
              manifest = "  s.files = %w[\n#{files}\n  ]\n"
         
     | 
| 
      
 124 
     | 
    
         
            +
              spec = [head, manifest, tail].join("  # = MANIFEST =\n")
         
     | 
| 
      
 125 
     | 
    
         
            +
              File.open(gemspec_file, 'w') { |io| io.write(spec) }
         
     | 
| 
      
 126 
     | 
    
         
            +
              puts "Updated #{gemspec_file}"
         
     | 
| 
      
 127 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,84 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ## This is the rakegem gemspec template. Make sure you read and understand
         
     | 
| 
      
 2 
     | 
    
         
            +
            ## all of the comments. Some sections require modification, and others can
         
     | 
| 
      
 3 
     | 
    
         
            +
            ## be deleted if you don't need them. Once you understand the contents of
         
     | 
| 
      
 4 
     | 
    
         
            +
            ## this file, feel free to delete any comments that begin with two hash marks.
         
     | 
| 
      
 5 
     | 
    
         
            +
            ## You can find comprehensive Gem::Specification documentation, at
         
     | 
| 
      
 6 
     | 
    
         
            +
            ## http://docs.rubygems.org/read/chapter/20
         
     | 
| 
      
 7 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.specification_version = 2 if s.respond_to? :specification_version=
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.rubygems_version = '1.3.5'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              ## Leave these as is they will be modified for you by the rake gemspec task.
         
     | 
| 
      
 13 
     | 
    
         
            +
              ## If your rubyforge_project name is different, then edit it and comment out
         
     | 
| 
      
 14 
     | 
    
         
            +
              ## the sub! line in the Rakefile
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.name              = 'em-rack-mongrel2'
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.version           = '0.1.0'
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.date              = '2012-01-13'
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.rubyforge_project = 'em-rack-mongrel2'
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              ## Make sure your summary is short. The description may be as long
         
     | 
| 
      
 21 
     | 
    
         
            +
              ## as you like.
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.summary     = %Q{A Mongrel2 Rack handler with EventMachine.}
         
     | 
| 
      
 23 
     | 
    
         
            +
              s.description = %Q{A Rack handler for the Mongrel2 web server with EventMachine support, by Zed Shaw. http://mongrel2.org/}
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              ## List the primary authors. If there are a bunch of authors, it's probably
         
     | 
| 
      
 26 
     | 
    
         
            +
              ## better to set the email to an email list or something. If you don't have
         
     | 
| 
      
 27 
     | 
    
         
            +
              ## a custom homepage, consider using your GitHub URL or the like.
         
     | 
| 
      
 28 
     | 
    
         
            +
              s.authors  = ['ICHIBANGASE, Yutaka']
         
     | 
| 
      
 29 
     | 
    
         
            +
              s.email    = 'yichiban@gmail.com'
         
     | 
| 
      
 30 
     | 
    
         
            +
              s.homepage = 'http://github.com/ichiban/em-rack-mongrel2'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
         
     | 
| 
      
 33 
     | 
    
         
            +
              ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
         
     | 
| 
      
 34 
     | 
    
         
            +
              s.require_paths = %w[lib]
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              ## Specify any RDoc options here. You'll want to add your README and
         
     | 
| 
      
 37 
     | 
    
         
            +
              ## LICENSE files to the extra_rdoc_files list.
         
     | 
| 
      
 38 
     | 
    
         
            +
              s.rdoc_options = ["--charset=UTF-8"]
         
     | 
| 
      
 39 
     | 
    
         
            +
              s.extra_rdoc_files = %w[README.md LICENSE]
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              ## List your runtime dependencies here. Runtime dependencies are those
         
     | 
| 
      
 42 
     | 
    
         
            +
              ## that are needed for an end user to actually USE your code.
         
     | 
| 
      
 43 
     | 
    
         
            +
              s.add_dependency('ffi', ['~> 1.0.0'])
         
     | 
| 
      
 44 
     | 
    
         
            +
              s.add_dependency('em-zeromq', ['~> 0.2.2'])
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              ## List your development dependencies here. Development dependencies are
         
     | 
| 
      
 47 
     | 
    
         
            +
              ## those that are only needed during development
         
     | 
| 
      
 48 
     | 
    
         
            +
              s.add_development_dependency('rspec', ['~> 2.3.0'])
         
     | 
| 
      
 49 
     | 
    
         
            +
              s.add_development_dependency('fuubar', ['~> 0.0.3'])
         
     | 
| 
      
 50 
     | 
    
         
            +
              s.add_development_dependency('yard', ['~> 0.6.4'])
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              ## Leave this section as-is. It will be automatically generated from the
         
     | 
| 
      
 53 
     | 
    
         
            +
              ## contents of your Git repository via the gemspec task. DO NOT REMOVE
         
     | 
| 
      
 54 
     | 
    
         
            +
              ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
         
     | 
| 
      
 55 
     | 
    
         
            +
              # = MANIFEST =
         
     | 
| 
      
 56 
     | 
    
         
            +
              s.files = %w[
         
     | 
| 
      
 57 
     | 
    
         
            +
                Gemfile
         
     | 
| 
      
 58 
     | 
    
         
            +
                LICENSE
         
     | 
| 
      
 59 
     | 
    
         
            +
                README.md
         
     | 
| 
      
 60 
     | 
    
         
            +
                Rakefile
         
     | 
| 
      
 61 
     | 
    
         
            +
                em-rack-mongrel2.gemspec
         
     | 
| 
      
 62 
     | 
    
         
            +
                example/.gitignore
         
     | 
| 
      
 63 
     | 
    
         
            +
                example/async_sinatra/app.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
                example/async_sinatra/config.ru
         
     | 
| 
      
 65 
     | 
    
         
            +
                example/mongrel2.conf
         
     | 
| 
      
 66 
     | 
    
         
            +
                example/sinatra/.gitignore
         
     | 
| 
      
 67 
     | 
    
         
            +
                example/sinatra/app.rb
         
     | 
| 
      
 68 
     | 
    
         
            +
                example/sinatra/config.ru
         
     | 
| 
      
 69 
     | 
    
         
            +
                lib/mongrel2.rb
         
     | 
| 
      
 70 
     | 
    
         
            +
                lib/mongrel2/connection.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
                lib/mongrel2/request.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
                lib/mongrel2/response.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
                lib/rack/handler/mongrel2.rb
         
     | 
| 
      
 74 
     | 
    
         
            +
                spec/request_spec.rb
         
     | 
| 
      
 75 
     | 
    
         
            +
                spec/response_spec.rb
         
     | 
| 
      
 76 
     | 
    
         
            +
                spec/spec.opts
         
     | 
| 
      
 77 
     | 
    
         
            +
                spec/spec_helper.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
              ]
         
     | 
| 
      
 79 
     | 
    
         
            +
              # = MANIFEST =
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              ## Test files will be grabbed from the file list. Make sure the path glob
         
     | 
| 
      
 82 
     | 
    
         
            +
              ## matches what you actually use.
         
     | 
| 
      
 83 
     | 
    
         
            +
              s.test_files = s.files.select { |path| path =~ /^spec\/.*_spec\.rb/ }
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
    
        data/example/.gitignore
    ADDED
    
    
| 
         @@ -0,0 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.unshift(File.expand_path('.')) # Ruby 1.9 doesn't have . in the load path...
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rack/handler/mongrel2'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'app'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Rack::Handler::Mongrel2.run AsyncExample, :uuid => 'sinatra', :block => true
         
     | 
| 
      
 8 
     | 
    
         
            +
            exit(0)
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            darkblog2 = Host(name='localhost', routes={
         
     | 
| 
      
 2 
     | 
    
         
            +
              '/': Handler(send_spec='tcp://127.0.0.1:9997',
         
     | 
| 
      
 3 
     | 
    
         
            +
                send_ident='9539ED88-1B33-4D19-A9F9-283E5BF11AC7',
         
     | 
| 
      
 4 
     | 
    
         
            +
                recv_spec='tcp://127.0.0.1:9996',
         
     | 
| 
      
 5 
     | 
    
         
            +
                recv_ident='')
         
     | 
| 
      
 6 
     | 
    
         
            +
              '/async/': Handler(send_spec='tcp://127.0.0.1:9999',
         
     | 
| 
      
 7 
     | 
    
         
            +
                send_ident='AEE66029-E420-42E7-A7C8-6C37BBFC7B9F',
         
     | 
| 
      
 8 
     | 
    
         
            +
                recv_spec='tcp://127.0.0.1:9998',
         
     | 
| 
      
 9 
     | 
    
         
            +
                recv_ident='')
         
     | 
| 
      
 10 
     | 
    
         
            +
            })
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            main = Server(
         
     | 
| 
      
 13 
     | 
    
         
            +
              uuid='94601E4B-A770-4B7D-930D-CE3A484B5280',
         
     | 
| 
      
 14 
     | 
    
         
            +
              chroot='.',
         
     | 
| 
      
 15 
     | 
    
         
            +
              access_log='/logs/mongrel2_access.log',
         
     | 
| 
      
 16 
     | 
    
         
            +
              error_log='/logs/mongrel2_error.log',
         
     | 
| 
      
 17 
     | 
    
         
            +
              pid_file='/tmp/pids/mongrel2.pid',
         
     | 
| 
      
 18 
     | 
    
         
            +
              default_host='localhost',
         
     | 
| 
      
 19 
     | 
    
         
            +
              name='main',
         
     | 
| 
      
 20 
     | 
    
         
            +
              port=8080,
         
     | 
| 
      
 21 
     | 
    
         
            +
              hosts=[darkblog2]
         
     | 
| 
      
 22 
     | 
    
         
            +
            )
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            settings = {
         
     | 
| 
      
 26 
     | 
    
         
            +
              'zeromq.threads': 1,
         
     | 
| 
      
 27 
     | 
    
         
            +
              'control_port': 'ipc://tmp/mongrel2_control'
         
     | 
| 
      
 28 
     | 
    
         
            +
            }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            servers = [main]
         
     | 
| 
         @@ -0,0 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.unshift(File.expand_path('.')) # Ruby 1.9 doesn't have . in the load path...
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rack/handler/mongrel2'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'app'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Rack::Handler::Mongrel2.run Sinatra::Application, :uuid => 'sinatra', :block => true
         
     | 
| 
      
 8 
     | 
    
         
            +
            exit(0)
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'em-zeromq'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mongrel2/request'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'mongrel2/response'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mongrel2
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Connection
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :received
         
     | 
| 
      
 8 
     | 
    
         
            +
                @context = nil
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def self.context
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @context ||= EM::ZeroMQ::Context.new(1)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(uuid, sub, pub, app)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @uuid, @sub, @pub, @app = uuid, sub, pub, app
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # Connect to receive requests
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @reqs = self.class.context.connect(ZMQ::PULL, sub, self)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # Connect to send responses
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @resp = self.class.context.connect(ZMQ::PUB, pub, nil, :identity => uuid)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def on_readable(socket, messages)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  messages.each do |msg|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    req = msg.nil? ? nil : Request.parse(msg.copy_out_string, self)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    next if req.nil? || req.disconnect?
         
     | 
| 
      
 28 
     | 
    
         
            +
                    process req
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def process(req)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  pre = Proc.new do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    method(:pre_process).call(req)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  post = Proc.new do |resp|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    method(:post_process).call(resp, req)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  EM.defer pre, post
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def pre_process(req)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  status, headers, rack_response = -1, {}, []
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  catch(:async) do
         
     | 
| 
      
 48 
     | 
    
         
            +
                    status, headers, rack_response = @app.call(req.env)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  [status, headers, rack_response]
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def post_process(response, req)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  status, headers, rack_response = *response
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # Status code -1 indicates that we're going to respond later (async).
         
     | 
| 
      
 57 
     | 
    
         
            +
                  return if -1 == status
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  body = ''
         
     | 
| 
      
 60 
     | 
    
         
            +
                  rack_response.each { |b| body << b }
         
     | 
| 
      
 61 
     | 
    
         
            +
                  reply req, body, status, headers
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def reply(req, body, status = 200, headers = {})
         
     | 
| 
      
 65 
     | 
    
         
            +
                  resp = Response.new(@resp)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  resp.send_http req, body, status, headers
         
     | 
| 
      
 67 
     | 
    
         
            +
                  resp.close req if req.close?
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def close
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # I think I should be able to just close the context
         
     | 
| 
      
 72 
     | 
    
         
            +
                  self.class.context.close rescue nil
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'mongrel2'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rack'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'eventmachine'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mongrel2
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Request
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :headers, :body, :uuid, :conn_id, :path, :connection
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def parse(msg, connection)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # UUID CONN_ID PATH SIZE:HEADERS,SIZE:BODY,
         
     | 
| 
      
 12 
     | 
    
         
            +
                    uuid, conn_id, path, rest = msg.split(' ', 4)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    headers, rest = parse_netstring(rest)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    body, _ = parse_netstring(rest)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    headers = Mongrel2::JSON.parse(headers)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    new(uuid, conn_id, path, headers, body, connection)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def parse_netstring(ns)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # SIZE:HEADERS,
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    len, rest = ns.split(':', 2)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    len = len.to_i
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise "Netstring did not end in ','" unless rest[len].chr == ','
         
     | 
| 
      
 25 
     | 
    
         
            +
                    [rest[0, len], rest[(len + 1)..-1]]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def initialize(uuid, conn_id, path, headers, body, connection)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @uuid, @conn_id, @path, @headers, @body = uuid, conn_id, path, headers, body
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @data = headers['METHOD'] == 'JSON' ? Mongrel2::JSON.parse(body) : {}
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @connection = connection
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def disconnect?
         
     | 
| 
      
 36 
     | 
    
         
            +
                  headers['METHOD'] == 'JSON' && @data['type'] == 'disconnect'
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def close?
         
     | 
| 
      
 40 
     | 
    
         
            +
                  headers['connection'] == 'close' || headers['VERSION'] == 'HTTP/1.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def env
         
     | 
| 
      
 44 
     | 
    
         
            +
                  script_name = ENV['RACK_RELATIVE_URL_ROOT'] || headers['PATTERN'].split('(', 2).first.gsub(/\/$/, '')
         
     | 
| 
      
 45 
     | 
    
         
            +
                  env = {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    'rack.version' => Rack::VERSION,
         
     | 
| 
      
 47 
     | 
    
         
            +
                    'rack.url_scheme' => 'http', # Only HTTP for now
         
     | 
| 
      
 48 
     | 
    
         
            +
                    'rack.input' => StringIO.new(body),
         
     | 
| 
      
 49 
     | 
    
         
            +
                    'rack.errors' => $stderr,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    'rack.multithread' => true,
         
     | 
| 
      
 51 
     | 
    
         
            +
                    'rack.multiprocess' => true,
         
     | 
| 
      
 52 
     | 
    
         
            +
                    'rack.run_once' => false,
         
     | 
| 
      
 53 
     | 
    
         
            +
                    'mongrel2.pattern' => headers['PATTERN'],
         
     | 
| 
      
 54 
     | 
    
         
            +
                    'REQUEST_METHOD' => headers['METHOD'],
         
     | 
| 
      
 55 
     | 
    
         
            +
                    'CONTENT_TYPE' => headers['content-type'],
         
     | 
| 
      
 56 
     | 
    
         
            +
                    'SCRIPT_NAME' => script_name,
         
     | 
| 
      
 57 
     | 
    
         
            +
                    'PATH_INFO' => headers['PATH'].gsub(script_name, ''),
         
     | 
| 
      
 58 
     | 
    
         
            +
                    'QUERY_STRING' => headers['QUERY'] || '',
         
     | 
| 
      
 59 
     | 
    
         
            +
                    'async.callback' => Proc.new { |resp|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      connection.method(:post_process).call(resp, self)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    },
         
     | 
| 
      
 62 
     | 
    
         
            +
                    'async.close' => EM::DefaultDeferrable.new
         
     | 
| 
      
 63 
     | 
    
         
            +
                  }
         
     | 
| 
      
 64 
     | 
    
         
            +
                  
         
     | 
| 
      
 65 
     | 
    
         
            +
                  env['SERVER_NAME'], env['SERVER_PORT'] = headers['host'].split(':', 2)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  headers.each do |key, val|
         
     | 
| 
      
 67 
     | 
    
         
            +
                    unless key =~ /content_(type|length)/i
         
     | 
| 
      
 68 
     | 
    
         
            +
                      key = "HTTP_#{key.upcase.gsub('-', '_')}"
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    env[key] = val
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  env
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Mongrel2
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Response
         
     | 
| 
      
 3 
     | 
    
         
            +
                StatusMessage = {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  100 => 'Continue',
         
     | 
| 
      
 5 
     | 
    
         
            +
                  101 => 'Switching Protocols',
         
     | 
| 
      
 6 
     | 
    
         
            +
                  200 => 'OK',
         
     | 
| 
      
 7 
     | 
    
         
            +
                  201 => 'Created',
         
     | 
| 
      
 8 
     | 
    
         
            +
                  202 => 'Accepted',
         
     | 
| 
      
 9 
     | 
    
         
            +
                  203 => 'Non-Authoritative Information',
         
     | 
| 
      
 10 
     | 
    
         
            +
                  204 => 'No Content',
         
     | 
| 
      
 11 
     | 
    
         
            +
                  205 => 'Reset Content',
         
     | 
| 
      
 12 
     | 
    
         
            +
                  206 => 'Partial Content',
         
     | 
| 
      
 13 
     | 
    
         
            +
                  300 => 'Multiple Choices',
         
     | 
| 
      
 14 
     | 
    
         
            +
                  301 => 'Moved Permanently',
         
     | 
| 
      
 15 
     | 
    
         
            +
                  302 => 'Found',
         
     | 
| 
      
 16 
     | 
    
         
            +
                  303 => 'See Other',
         
     | 
| 
      
 17 
     | 
    
         
            +
                  304 => 'Not Modified',
         
     | 
| 
      
 18 
     | 
    
         
            +
                  305 => 'Use Proxy',
         
     | 
| 
      
 19 
     | 
    
         
            +
                  307 => 'Temporary Redirect',
         
     | 
| 
      
 20 
     | 
    
         
            +
                  400 => 'Bad Request',
         
     | 
| 
      
 21 
     | 
    
         
            +
                  401 => 'Unauthorized',
         
     | 
| 
      
 22 
     | 
    
         
            +
                  402 => 'Payment Required',
         
     | 
| 
      
 23 
     | 
    
         
            +
                  403 => 'Forbidden',
         
     | 
| 
      
 24 
     | 
    
         
            +
                  404 => 'Not Found',
         
     | 
| 
      
 25 
     | 
    
         
            +
                  405 => 'Method Not Allowed',
         
     | 
| 
      
 26 
     | 
    
         
            +
                  406 => 'Not Acceptable',
         
     | 
| 
      
 27 
     | 
    
         
            +
                  407 => 'Proxy Authentication Required',
         
     | 
| 
      
 28 
     | 
    
         
            +
                  408 => 'Request Timeout',
         
     | 
| 
      
 29 
     | 
    
         
            +
                  409 => 'Conflict',
         
     | 
| 
      
 30 
     | 
    
         
            +
                  410 => 'Gone',
         
     | 
| 
      
 31 
     | 
    
         
            +
                  411 => 'Length Required',
         
     | 
| 
      
 32 
     | 
    
         
            +
                  412 => 'Precondition Failed',
         
     | 
| 
      
 33 
     | 
    
         
            +
                  413 => 'Request Entity Too Large',
         
     | 
| 
      
 34 
     | 
    
         
            +
                  414 => 'Request-URI Too Large',
         
     | 
| 
      
 35 
     | 
    
         
            +
                  415 => 'Unsupported Media Type',
         
     | 
| 
      
 36 
     | 
    
         
            +
                  416 => 'Request Range Not Satisfiable',
         
     | 
| 
      
 37 
     | 
    
         
            +
                  417 => 'Expectation Failed',
         
     | 
| 
      
 38 
     | 
    
         
            +
                  500 => 'Internal Server Error',
         
     | 
| 
      
 39 
     | 
    
         
            +
                  501 => 'Not Implemented',
         
     | 
| 
      
 40 
     | 
    
         
            +
                  502 => 'Bad Gateway',
         
     | 
| 
      
 41 
     | 
    
         
            +
                  503 => 'Service Unavailable',
         
     | 
| 
      
 42 
     | 
    
         
            +
                  504 => 'Gateway Timeout',
         
     | 
| 
      
 43 
     | 
    
         
            +
                  505 => 'HTTP Version Not Supported'
         
     | 
| 
      
 44 
     | 
    
         
            +
                }
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def initialize(resp)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @resp = resp
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def send_http(req, body, status, headers)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  send_resp(req.uuid, req.conn_id, build_http_response(body, status, headers))
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def close(req)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  send_resp(req.uuid, req.conn_id, '')
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              private
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def send_resp(uuid, conn_id, data)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @resp.send_msg('%s %d:%s, %s' % [uuid, conn_id.size, conn_id, data])
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def build_http_response(body, status, headers)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  headers['Content-Length'] = body.size.to_s
         
     | 
| 
      
 66 
     | 
    
         
            +
                  headers = headers.map{ |k, v| '%s: %s' % [k,v] }.join("\r\n")
         
     | 
| 
      
 67 
     | 
    
         
            +
                  "HTTP/1.1 #{status} #{StatusMessage[status.to_i]}\r\n#{headers}\r\n\r\n#{body}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/mongrel2.rb
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            begin
         
     | 
| 
      
 2 
     | 
    
         
            +
              require 'yajl'
         
     | 
| 
      
 3 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 4 
     | 
    
         
            +
              begin
         
     | 
| 
      
 5 
     | 
    
         
            +
                require 'json'
         
     | 
| 
      
 6 
     | 
    
         
            +
              rescue LoadError
         
     | 
| 
      
 7 
     | 
    
         
            +
                raise "You need either the yajl-ruby or json gems present in order to parse JSON!"
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            module Mongrel2
         
     | 
| 
      
 12 
     | 
    
         
            +
              JSON = Object.const_defined?('Yajl') ? ::Yajl::Parser : ::JSON
         
     | 
| 
      
 13 
     | 
    
         
            +
              VERSION = '0.1.0'
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'mongrel2/connection'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'stringio'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'eventmachine'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Handler
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Mongrel2
         
     | 
| 
      
 8 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def run(app, options = {})
         
     | 
| 
      
 10 
     | 
    
         
            +
                      options = {
         
     | 
| 
      
 11 
     | 
    
         
            +
                        :recv => ENV['RACK_MONGREL2_RECV'] || 'tcp://127.0.0.1:9997',
         
     | 
| 
      
 12 
     | 
    
         
            +
                        :send => ENV['RACK_MONGREL2_SEND'] || 'tcp://127.0.0.1:9996',
         
     | 
| 
      
 13 
     | 
    
         
            +
                        :uuid => ENV['RACK_MONGREL2_UUID']
         
     | 
| 
      
 14 
     | 
    
         
            +
                      }.merge(options)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      raise ArgumentError.new('Must specify an :uuid or set RACK_MONGREL2_UUID') if options[:uuid].nil?
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      conn = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                      EM.run do
         
     | 
| 
      
 21 
     | 
    
         
            +
                        conn = ::Mongrel2::Connection.new(options[:uuid], options[:recv], options[:send], app)
         
     | 
| 
      
 22 
     | 
    
         
            +
                        
         
     | 
| 
      
 23 
     | 
    
         
            +
                        # This doesn't work at all until zmq fixes their shit (in 2.1.x I think), but trap it now anyway.
         
     | 
| 
      
 24 
     | 
    
         
            +
                        %w(INT TERM KILL).each do |sig|
         
     | 
| 
      
 25 
     | 
    
         
            +
                          trap(sig) do
         
     | 
| 
      
 26 
     | 
    
         
            +
                            conn.close
         
     | 
| 
      
 27 
     | 
    
         
            +
                            EM.stop
         
     | 
| 
      
 28 
     | 
    
         
            +
                          end
         
     | 
| 
      
 29 
     | 
    
         
            +
                        end
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 32 
     | 
    
         
            +
                      conn.close if conn.respond_to?(:close)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mongrel2/request'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe Mongrel2::Request do
         
     | 
| 
      
 5 
     | 
    
         
            +
              it 'should parse a netstring and ignore the contents of the netstring as well as the trailing comma' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                netstring = '9:aoeu:snth,'
         
     | 
| 
      
 7 
     | 
    
         
            +
                result = Mongrel2::Request.parse_netstring(netstring)
         
     | 
| 
      
 8 
     | 
    
         
            +
                result.length.should == 2
         
     | 
| 
      
 9 
     | 
    
         
            +
                result[0].length.should == 9
         
     | 
| 
      
 10 
     | 
    
         
            +
                result[0].should eql('aoeu:snth')
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it 'should parse a netstring made up of multiple netstrings' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                netstring = '9:aoeu:snth,16:aeou snth qwerty,'
         
     | 
| 
      
 15 
     | 
    
         
            +
                result = Mongrel2::Request.parse_netstring(netstring)
         
     | 
| 
      
 16 
     | 
    
         
            +
                result.length.should == 2
         
     | 
| 
      
 17 
     | 
    
         
            +
                result[0].length.should == 9
         
     | 
| 
      
 18 
     | 
    
         
            +
                result[0].should eql('aoeu:snth')
         
     | 
| 
      
 19 
     | 
    
         
            +
                result[1].length.should == 20
         
     | 
| 
      
 20 
     | 
    
         
            +
                result[1].should eql('16:aeou snth qwerty,')
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              it 'should fail if the netstring does not end in a comma' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                expect { Mongrel2::Request.parse_netstring('3:foo') }.to raise_error(NameError)
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              it "should parse a Mongrel2 message and have all parts populated" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                netstring = "UUID CON PATH 253:{\"PATH\":\"/\",\"user-agent\":\"curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3\",\"host\":\"localhost:6767\",\"accept\":\"*/*\",\"connection\":\"close\",\"x-forwarded-for\":\"::1\",\"METHOD\":\"GET\",\"VERSION\":\"HTTP/1.1\",\"URI\":\"/\",\"PATTERN\":\"/\"},0:,"
         
     | 
| 
      
 29 
     | 
    
         
            +
                r = Mongrel2::Request.parse(netstring, double())
         
     | 
| 
      
 30 
     | 
    
         
            +
                r.should_not be_nil
         
     | 
| 
      
 31 
     | 
    
         
            +
                r.uuid.should eql('UUID')
         
     | 
| 
      
 32 
     | 
    
         
            +
                r.conn_id.should eql('CON')
         
     | 
| 
      
 33 
     | 
    
         
            +
                r.path.should eql('PATH')
         
     | 
| 
      
 34 
     | 
    
         
            +
                r.body.length.should == 0
         
     | 
| 
      
 35 
     | 
    
         
            +
                r.headers.length.should == 10
         
     | 
| 
      
 36 
     | 
    
         
            +
                r.headers['PATH'].should eql('/')
         
     | 
| 
      
 37 
     | 
    
         
            +
                r.headers['user-agent'].should eql('curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3')
         
     | 
| 
      
 38 
     | 
    
         
            +
                r.headers['host'].should eql('localhost:6767')
         
     | 
| 
      
 39 
     | 
    
         
            +
                r.headers['accept'].should eql('*/*')
         
     | 
| 
      
 40 
     | 
    
         
            +
                r.headers['x-forwarded-for'].should eql('::1')
         
     | 
| 
      
 41 
     | 
    
         
            +
                r.headers['METHOD'].should eql('GET')
         
     | 
| 
      
 42 
     | 
    
         
            +
                r.headers['VERSION'].should eql('HTTP/1.1')
         
     | 
| 
      
 43 
     | 
    
         
            +
                r.headers['URI'].should eql('/')
         
     | 
| 
      
 44 
     | 
    
         
            +
                r.headers['PATTERN'].should eql('/')
         
     | 
| 
      
 45 
     | 
    
         
            +
                r.close?.should be_true
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              it "should return rack env with async callbacks" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                netstring = "UUID CON PATH 253:{\"PATH\":\"/\",\"user-agent\":\"curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3\",\"host\":\"localhost:6767\",\"accept\":\"*/*\",\"connection\":\"close\",\"x-forwarded-for\":\"::1\",\"METHOD\":\"GET\",\"VERSION\":\"HTTP/1.1\",\"URI\":\"/\",\"PATTERN\":\"/\"},0:,"
         
     | 
| 
      
 50 
     | 
    
         
            +
                response = double("response")
         
     | 
| 
      
 51 
     | 
    
         
            +
                connection = double("connection")
         
     | 
| 
      
 52 
     | 
    
         
            +
                r = Mongrel2::Request.parse(netstring, connection)
         
     | 
| 
      
 53 
     | 
    
         
            +
                connection.should_receive(:post_process).with(response, r)
         
     | 
| 
      
 54 
     | 
    
         
            +
                env = r.env
         
     | 
| 
      
 55 
     | 
    
         
            +
                env['async.callback'].call(response)
         
     | 
| 
      
 56 
     | 
    
         
            +
                env['async.close'].should_not be_nil
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mongrel2/response'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe Mongrel2::Response do
         
     | 
| 
      
 5 
     | 
    
         
            +
              before(:each) do
         
     | 
| 
      
 6 
     | 
    
         
            +
                @req = double()
         
     | 
| 
      
 7 
     | 
    
         
            +
                @resp = double()
         
     | 
| 
      
 8 
     | 
    
         
            +
                @response = Mongrel2::Response.new(@resp)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it 'should build the HTTP request format' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                @req.should_receive(:uuid) { 'UUID' }
         
     | 
| 
      
 13 
     | 
    
         
            +
                @req.should_receive(:conn_id) { 'CONN_ID' }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                httpreq = "UUID 7:CONN_ID, HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\nBoo!"
         
     | 
| 
      
 16 
     | 
    
         
            +
                @resp.should_receive(:send_msg).with(httpreq)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                @response.send_http(@req, 'Boo!', 200, {})
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              it 'should send a blank response to close the response' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                @req.should_receive(:uuid) { 'UUID' }
         
     | 
| 
      
 23 
     | 
    
         
            +
                @req.should_receive(:conn_id) { 'CONN_ID' }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                httpreq = 'UUID 7:CONN_ID, '
         
     | 
| 
      
 26 
     | 
    
         
            +
                @resp.should_receive(:send_msg).with(httpreq)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                @response.close(@req)
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec.opts
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --color
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,166 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: em-rack-mongrel2
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              hash: 27
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
              segments: 
         
     | 
| 
      
 7 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 8 
     | 
    
         
            +
              - 1
         
     | 
| 
      
 9 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 10 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 12 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 13 
     | 
    
         
            +
            - ICHIBANGASE, Yutaka
         
     | 
| 
      
 14 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 16 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            date: 2012-01-13 00:00:00 Z
         
     | 
| 
      
 19 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 20 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 21 
     | 
    
         
            +
              name: ffi
         
     | 
| 
      
 22 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 23 
     | 
    
         
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 24 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 25 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 26 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 27 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    hash: 23
         
     | 
| 
      
 29 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 31 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 32 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: 1.0.0
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *id001
         
     | 
| 
      
 36 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 37 
     | 
    
         
            +
              name: em-zeromq
         
     | 
| 
      
 38 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 39 
     | 
    
         
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 40 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 41 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 42 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 43 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 44 
     | 
    
         
            +
                    hash: 19
         
     | 
| 
      
 45 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 46 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 48 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 49 
     | 
    
         
            +
                    version: 0.2.2
         
     | 
| 
      
 50 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 51 
     | 
    
         
            +
              version_requirements: *id002
         
     | 
| 
      
 52 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 53 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 54 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 55 
     | 
    
         
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 56 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 57 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 60 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 61 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 62 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 63 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 64 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                    version: 2.3.0
         
     | 
| 
      
 66 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 67 
     | 
    
         
            +
              version_requirements: *id003
         
     | 
| 
      
 68 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 69 
     | 
    
         
            +
              name: fuubar
         
     | 
| 
      
 70 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 72 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 73 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 74 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 75 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 76 
     | 
    
         
            +
                    hash: 25
         
     | 
| 
      
 77 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 78 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 79 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 80 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 81 
     | 
    
         
            +
                    version: 0.0.3
         
     | 
| 
      
 82 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 83 
     | 
    
         
            +
              version_requirements: *id004
         
     | 
| 
      
 84 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 85 
     | 
    
         
            +
              name: yard
         
     | 
| 
      
 86 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 87 
     | 
    
         
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 88 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 89 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 90 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 91 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 92 
     | 
    
         
            +
                    hash: 15
         
     | 
| 
      
 93 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 94 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 95 
     | 
    
         
            +
                    - 6
         
     | 
| 
      
 96 
     | 
    
         
            +
                    - 4
         
     | 
| 
      
 97 
     | 
    
         
            +
                    version: 0.6.4
         
     | 
| 
      
 98 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 99 
     | 
    
         
            +
              version_requirements: *id005
         
     | 
| 
      
 100 
     | 
    
         
            +
            description: A Rack handler for the Mongrel2 web server with EventMachine support, by Zed Shaw. http://mongrel2.org/
         
     | 
| 
      
 101 
     | 
    
         
            +
            email: yichiban@gmail.com
         
     | 
| 
      
 102 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            extra_rdoc_files: 
         
     | 
| 
      
 107 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 108 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 109 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 110 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 111 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 112 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 113 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 114 
     | 
    
         
            +
            - em-rack-mongrel2.gemspec
         
     | 
| 
      
 115 
     | 
    
         
            +
            - example/.gitignore
         
     | 
| 
      
 116 
     | 
    
         
            +
            - example/async_sinatra/app.rb
         
     | 
| 
      
 117 
     | 
    
         
            +
            - example/async_sinatra/config.ru
         
     | 
| 
      
 118 
     | 
    
         
            +
            - example/mongrel2.conf
         
     | 
| 
      
 119 
     | 
    
         
            +
            - example/sinatra/.gitignore
         
     | 
| 
      
 120 
     | 
    
         
            +
            - example/sinatra/app.rb
         
     | 
| 
      
 121 
     | 
    
         
            +
            - example/sinatra/config.ru
         
     | 
| 
      
 122 
     | 
    
         
            +
            - lib/mongrel2.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - lib/mongrel2/connection.rb
         
     | 
| 
      
 124 
     | 
    
         
            +
            - lib/mongrel2/request.rb
         
     | 
| 
      
 125 
     | 
    
         
            +
            - lib/mongrel2/response.rb
         
     | 
| 
      
 126 
     | 
    
         
            +
            - lib/rack/handler/mongrel2.rb
         
     | 
| 
      
 127 
     | 
    
         
            +
            - spec/request_spec.rb
         
     | 
| 
      
 128 
     | 
    
         
            +
            - spec/response_spec.rb
         
     | 
| 
      
 129 
     | 
    
         
            +
            - spec/spec.opts
         
     | 
| 
      
 130 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 131 
     | 
    
         
            +
            homepage: http://github.com/ichiban/em-rack-mongrel2
         
     | 
| 
      
 132 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 135 
     | 
    
         
            +
            rdoc_options: 
         
     | 
| 
      
 136 
     | 
    
         
            +
            - --charset=UTF-8
         
     | 
| 
      
 137 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 138 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 139 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 140 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 141 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 142 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 143 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 144 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 145 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 146 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 147 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 148 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 149 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 150 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 151 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 152 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 153 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 154 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 155 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 156 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 157 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
            rubyforge_project: em-rack-mongrel2
         
     | 
| 
      
 160 
     | 
    
         
            +
            rubygems_version: 1.8.11
         
     | 
| 
      
 161 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 162 
     | 
    
         
            +
            specification_version: 2
         
     | 
| 
      
 163 
     | 
    
         
            +
            summary: A Mongrel2 Rack handler with EventMachine.
         
     | 
| 
      
 164 
     | 
    
         
            +
            test_files: 
         
     | 
| 
      
 165 
     | 
    
         
            +
            - spec/request_spec.rb
         
     | 
| 
      
 166 
     | 
    
         
            +
            - spec/response_spec.rb
         
     |