mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Name change: Mongrel => Puma
This commit is contained in:
parent
ec2d820ae5
commit
190a81c55a
40 changed files with 285 additions and 300 deletions
46
Manifest.txt
46
Manifest.txt
|
@ -5,14 +5,14 @@ Manifest.txt
|
|||
README.txt
|
||||
Rakefile
|
||||
TODO
|
||||
bin/mongrel_rails
|
||||
bin/puma_rails
|
||||
examples/builder.rb
|
||||
examples/camping/README
|
||||
examples/camping/blog.rb
|
||||
examples/camping/tepee.rb
|
||||
examples/httpd.conf
|
||||
examples/mime.yaml
|
||||
examples/mongrel.conf
|
||||
examples/puma.conf
|
||||
examples/monitrc
|
||||
examples/random_thrash.rb
|
||||
examples/simpletest.rb
|
||||
|
@ -26,32 +26,32 @@ ext/http11/http11_parser.java.rl
|
|||
ext/http11/http11_parser.rl
|
||||
ext/http11/http11_parser_common.rl
|
||||
ext/http11/Http11Service.java
|
||||
ext/http11/org/jruby/mongrel/Http11.java
|
||||
ext/http11/org/jruby/mongrel/Http11Parser.java
|
||||
lib/mongrel.rb
|
||||
lib/mongrel/camping.rb
|
||||
lib/mongrel/cgi.rb
|
||||
lib/mongrel/command.rb
|
||||
lib/mongrel/configurator.rb
|
||||
lib/mongrel/const.rb
|
||||
lib/mongrel/debug.rb
|
||||
lib/mongrel/gems.rb
|
||||
lib/mongrel/handlers.rb
|
||||
lib/mongrel/header_out.rb
|
||||
lib/mongrel/http_request.rb
|
||||
lib/mongrel/http_response.rb
|
||||
lib/mongrel/init.rb
|
||||
lib/mongrel/mime_types.yml
|
||||
lib/mongrel/rails.rb
|
||||
lib/mongrel/stats.rb
|
||||
lib/mongrel/tcphack.rb
|
||||
lib/mongrel/uri_classifier.rb
|
||||
ext/http11/org/jruby/puma/Http11.java
|
||||
ext/http11/org/jruby/puma/Http11Parser.java
|
||||
lib/puma.rb
|
||||
lib/puma/camping.rb
|
||||
lib/puma/cgi.rb
|
||||
lib/puma/command.rb
|
||||
lib/puma/configurator.rb
|
||||
lib/puma/const.rb
|
||||
lib/puma/debug.rb
|
||||
lib/puma/gems.rb
|
||||
lib/puma/handlers.rb
|
||||
lib/puma/header_out.rb
|
||||
lib/puma/http_request.rb
|
||||
lib/puma/http_response.rb
|
||||
lib/puma/init.rb
|
||||
lib/puma/mime_types.yml
|
||||
lib/puma/rails.rb
|
||||
lib/puma/stats.rb
|
||||
lib/puma/tcphack.rb
|
||||
lib/puma/uri_classifier.rb
|
||||
setup.rb
|
||||
tasks/gem.rake
|
||||
tasks/native.rake
|
||||
tasks/ragel.rake
|
||||
test/mime.yaml
|
||||
test/mongrel.conf
|
||||
test/puma.conf
|
||||
test/test_cgi_wrapper.rb
|
||||
test/test_command.rb
|
||||
test/test_conditional.rb
|
||||
|
|
|
@ -3,24 +3,24 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# Additional work donated by contributors. See http://puma.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'yaml'
|
||||
require 'etc'
|
||||
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
||||
require 'mongrel'
|
||||
require 'mongrel/rails'
|
||||
require 'puma'
|
||||
require 'puma/rails'
|
||||
|
||||
Mongrel::Gems.require 'gem_plugin'
|
||||
Puma::Gems.require 'gem_plugin'
|
||||
|
||||
# require 'ruby-debug'
|
||||
# Debugger.start
|
||||
|
||||
module Mongrel
|
||||
module Puma
|
||||
class Start < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
include Puma::Command::Base
|
||||
|
||||
def configure
|
||||
options [
|
||||
|
@ -28,8 +28,8 @@ module Mongrel
|
|||
["-d", "--daemonize", "Run daemonized in the background", :@daemon, false],
|
||||
['-p', '--port PORT', "Which port to bind to", :@port, 3000],
|
||||
['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
|
||||
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
|
||||
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"],
|
||||
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/puma.log"],
|
||||
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/puma.pid"],
|
||||
['-n', '--num-processors INT', "Number of processors active before clients denied", :@num_processors, 1024],
|
||||
['-o', '--timeout TIME', "Time to wait (in seconds) before killing a stalled thread", :@timeout, 60],
|
||||
['-t', '--throttle TIME', "Time to pause (in hundredths of a second) between accepting clients", :@throttle, 0],
|
||||
|
@ -79,15 +79,15 @@ module Mongrel
|
|||
@generate = File.expand_path(@generate)
|
||||
STDERR.puts "** Writing config to \"#@generate\"."
|
||||
open(@generate, "w") {|f| f.write(settings.to_yaml) }
|
||||
STDERR.puts "** Finished. Run \"mongrel_rails start -C #@generate\" to use the config file."
|
||||
STDERR.puts "** Finished. Run \"puma_rails start -C #@generate\" to use the config file."
|
||||
exit 0
|
||||
end
|
||||
|
||||
config = Mongrel::Rails::RailsConfigurator.new(settings) do
|
||||
config = Puma::Rails::RailsConfigurator.new(settings) do
|
||||
if defaults[:daemon]
|
||||
if File.exist? defaults[:pid_file]
|
||||
log "!!! PID file #{defaults[:pid_file]} already exists. Mongrel could be running already. Check your #{defaults[:log_file]} for errors."
|
||||
log "!!! Exiting with error. You must stop mongrel and clear the .pid before I'll attempt a start."
|
||||
log "!!! PID file #{defaults[:pid_file]} already exists. Puma could be running already. Check your #{defaults[:log_file]} for errors."
|
||||
log "!!! Exiting with error. You must stop puma and clear the .pid before I'll attempt a start."
|
||||
exit 1
|
||||
end
|
||||
|
||||
|
@ -97,7 +97,7 @@ module Mongrel
|
|||
log "Settings loaded from #{@config_file} (they override command line)." if @config_file
|
||||
end
|
||||
|
||||
log "Starting Mongrel listening at #{defaults[:host]}:#{defaults[:port]}"
|
||||
log "Starting Puma listening at #{defaults[:host]}:#{defaults[:port]}"
|
||||
|
||||
listener do
|
||||
mime = {}
|
||||
|
@ -107,7 +107,7 @@ module Mongrel
|
|||
end
|
||||
|
||||
if defaults[:debug]
|
||||
log "Installing debugging prefixed filters. Look in log/mongrel_debug for the files."
|
||||
log "Installing debugging prefixed filters. Look in log/puma_debug for the files."
|
||||
debug "/"
|
||||
end
|
||||
|
||||
|
@ -129,7 +129,7 @@ module Mongrel
|
|||
end
|
||||
|
||||
config.run
|
||||
config.log "Mongrel #{Mongrel::Const::MONGREL_VERSION} available at #{@address}:#{@port}"
|
||||
config.log "Puma #{Puma::Const::PUMA_VERSION} available at #{@address}:#{@port}"
|
||||
|
||||
unless config.defaults[:daemon]
|
||||
config.log "Use CTRL-C to stop."
|
||||
|
@ -164,7 +164,7 @@ module Mongrel
|
|||
STDERR.puts "** Loading settings from #{@config_file} (they override command line)." unless @daemon || settings[:daemon]
|
||||
end
|
||||
|
||||
settings[:includes] ||= ["mongrel"]
|
||||
settings[:includes] ||= ["puma"]
|
||||
|
||||
# Config file settings will override command line settings
|
||||
settings.each do |key, value|
|
||||
|
@ -194,9 +194,9 @@ module Mongrel
|
|||
end
|
||||
end
|
||||
|
||||
def Mongrel::send_signal(signal, pid_file)
|
||||
def Puma::send_signal(signal, pid_file)
|
||||
pid = File.read(pid_file).to_i
|
||||
print "Sending #{signal} to Mongrel at PID #{pid}..."
|
||||
print "Sending #{signal} to Puma at PID #{pid}..."
|
||||
begin
|
||||
Process.kill(signal, pid)
|
||||
rescue Errno::ESRCH
|
||||
|
@ -208,14 +208,14 @@ module Mongrel
|
|||
|
||||
|
||||
class Stop < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
include Puma::Command::Base
|
||||
|
||||
def configure
|
||||
options [
|
||||
['-c', '--chdir PATH', "Change to dir before starting (will be expanded).", :@cwd, "."],
|
||||
['-f', '--force', "Force the shutdown (kill -9).", :@force, false],
|
||||
['-w', '--wait SECONDS', "Wait SECONDS before forcing shutdown", :@wait, "0"],
|
||||
['-P', '--pid FILE', "Where the PID file is located.", :@pid_file, "log/mongrel.pid"]
|
||||
['-P', '--pid FILE', "Where the PID file is located.", :@pid_file, "log/puma.pid"]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -236,22 +236,22 @@ module Mongrel
|
|||
sleep 1
|
||||
end
|
||||
|
||||
Mongrel::send_signal("KILL", @pid_file) if File.exist? @pid_file
|
||||
Puma::send_signal("KILL", @pid_file) if File.exist? @pid_file
|
||||
else
|
||||
Mongrel::send_signal("TERM", @pid_file)
|
||||
Puma::send_signal("TERM", @pid_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Restart < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
include Puma::Command::Base
|
||||
|
||||
def configure
|
||||
options [
|
||||
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, '.'],
|
||||
['-s', '--soft', "Do a soft restart rather than a process exit restart", :@soft, false],
|
||||
['-P', '--pid FILE', "Where the PID file is located", :@pid_file, "log/mongrel.pid"]
|
||||
['-P', '--pid FILE', "Where the PID file is located", :@pid_file, "log/puma.pid"]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -267,18 +267,18 @@ module Mongrel
|
|||
|
||||
def run
|
||||
if @soft
|
||||
Mongrel::send_signal("HUP", @pid_file)
|
||||
Puma::send_signal("HUP", @pid_file)
|
||||
else
|
||||
Mongrel::send_signal("USR2", @pid_file)
|
||||
Puma::send_signal("USR2", @pid_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
|
||||
GemPlugin::Manager.instance.load "puma" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
|
||||
|
||||
|
||||
if not Mongrel::Command::Registry.instance.run ARGV
|
||||
if not Puma::Command::Registry.instance.run ARGV
|
||||
exit 1
|
||||
end
|
||||
|
|
|
@ -456,7 +456,7 @@ VALUE HttpParser_body(VALUE self) {
|
|||
void Init_http11()
|
||||
{
|
||||
|
||||
VALUE mMongrel = rb_define_module("Mongrel");
|
||||
VALUE mPuma = rb_define_module("Puma");
|
||||
|
||||
DEF_GLOBAL(request_method, "REQUEST_METHOD");
|
||||
DEF_GLOBAL(request_uri, "REQUEST_URI");
|
||||
|
@ -465,10 +465,10 @@ void Init_http11()
|
|||
DEF_GLOBAL(http_version, "HTTP_VERSION");
|
||||
DEF_GLOBAL(request_path, "REQUEST_PATH");
|
||||
|
||||
eHttpParserError = rb_define_class_under(mMongrel, "HttpParserError", rb_eIOError);
|
||||
eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eIOError);
|
||||
rb_global_variable(&eHttpParserError);
|
||||
|
||||
VALUE cHttpParser = rb_define_class_under(mMongrel, "HttpParser", rb_cObject);
|
||||
VALUE cHttpParser = rb_define_class_under(mPuma, "HttpParser", rb_cObject);
|
||||
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
|
||||
rb_define_method(cHttpParser, "initialize", HttpParser_init, 0);
|
||||
rb_define_method(cHttpParser, "reset", HttpParser_reset, 0);
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
|
||||
# Standard libraries
|
||||
require 'socket'
|
||||
require 'tempfile'
|
||||
require 'yaml'
|
||||
require 'time'
|
||||
require 'etc'
|
||||
require 'uri'
|
||||
require 'stringio'
|
||||
|
||||
# Compiled Mongrel extension
|
||||
# support multiple ruby version (fat binaries under windows)
|
||||
begin
|
||||
RUBY_VERSION =~ /(\d+.\d+)/
|
||||
require "#{$1}/http11"
|
||||
rescue LoadError
|
||||
require 'http11'
|
||||
end
|
||||
|
||||
# Gem conditional loader
|
||||
require 'mongrel/gems'
|
||||
require 'thread'
|
||||
|
||||
# Ruby Mongrel
|
||||
require 'mongrel/handlers'
|
||||
require 'mongrel/command'
|
||||
require 'mongrel/tcphack'
|
||||
require 'mongrel/configurator'
|
||||
require 'mongrel/uri_classifier'
|
||||
require 'mongrel/const'
|
||||
require 'mongrel/http_request'
|
||||
require 'mongrel/header_out'
|
||||
require 'mongrel/http_response'
|
||||
require 'mongrel/server'
|
||||
|
||||
# Mongrel module containing all of the classes (include C extensions)
|
||||
# for running a Mongrel web server. It contains a minimalist HTTP server
|
||||
# with just enough functionality to service web application requests
|
||||
# fast as possible.
|
||||
module Mongrel
|
||||
|
||||
# Thrown at a thread when it is timed out.
|
||||
class TimeoutError < RuntimeError; end
|
||||
|
||||
class BodyReadError < RuntimeError; end
|
||||
end
|
||||
|
||||
Mongrel::Gems.require "mongrel_experimental",
|
||||
">=#{Mongrel::Const::MONGREL_VERSION}"
|
|
@ -1,10 +0,0 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'mongrel/gems'
|
||||
Mongrel::Gems.require 'gem_plugin'
|
||||
|
||||
# File is just a stub that makes sure the mongrel_plugins gem is loaded and ready
|
49
lib/puma.rb
Normal file
49
lib/puma.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
# Standard libraries
|
||||
require 'socket'
|
||||
require 'tempfile'
|
||||
require 'yaml'
|
||||
require 'time'
|
||||
require 'etc'
|
||||
require 'uri'
|
||||
require 'stringio'
|
||||
|
||||
# Compiled Puma extension
|
||||
# support multiple ruby version (fat binaries under windows)
|
||||
begin
|
||||
RUBY_VERSION =~ /(\d+.\d+)/
|
||||
require "#{$1}/http11"
|
||||
rescue LoadError
|
||||
require 'http11'
|
||||
end
|
||||
|
||||
# Gem conditional loader
|
||||
require 'puma/gems'
|
||||
require 'thread'
|
||||
|
||||
# Ruby Puma
|
||||
require 'puma/handlers'
|
||||
require 'puma/command'
|
||||
require 'puma/tcphack'
|
||||
require 'puma/configurator'
|
||||
require 'puma/uri_classifier'
|
||||
require 'puma/const'
|
||||
require 'puma/http_request'
|
||||
require 'puma/header_out'
|
||||
require 'puma/http_response'
|
||||
require 'puma/server'
|
||||
|
||||
# Puma module containing all of the classes (include C extensions)
|
||||
# for running a Puma web server. It contains a minimalist HTTP server
|
||||
# with just enough functionality to service web application requests
|
||||
# fast as possible.
|
||||
module Puma
|
||||
|
||||
# Thrown at a thread when it is timed out.
|
||||
class TimeoutError < RuntimeError; end
|
||||
|
||||
class BodyReadError < RuntimeError; end
|
||||
end
|
||||
|
||||
Puma::Gems.require "puma_experimental",
|
||||
">=#{Puma::Const::PUMA_VERSION}"
|
|
@ -1,26 +1,25 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# Copyright (c) 2011 Evan Phoenix
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'singleton'
|
||||
require 'optparse'
|
||||
|
||||
require 'mongrel/gems'
|
||||
Mongrel::Gems.require 'gem_plugin'
|
||||
require 'puma/gems'
|
||||
Puma::Gems.require 'gem_plugin'
|
||||
|
||||
module Mongrel
|
||||
module Puma
|
||||
|
||||
# Contains all of the various commands that are used with
|
||||
# Mongrel servers.
|
||||
# Puma servers.
|
||||
|
||||
module Command
|
||||
|
||||
BANNER = "Usage: mongrel_rails <command> [options]"
|
||||
BANNER = "Usage: puma_rails <command> [options]"
|
||||
|
||||
# A Command pattern implementation used to create the set of command available to the user
|
||||
# from Mongrel. The script uses objects which implement this interface to do the
|
||||
# from Puma. The script uses objects which implement this interface to do the
|
||||
# user's bidding.
|
||||
module Base
|
||||
|
||||
|
@ -44,7 +43,7 @@ module Mongrel
|
|||
def initialize(options={})
|
||||
argv = options[:argv] || []
|
||||
@opt = OptionParser.new
|
||||
@opt.banner = Mongrel::Command::BANNER
|
||||
@opt.banner = Puma::Command::BANNER
|
||||
@valid = true
|
||||
# this is retarded, but it has to be done this way because -h and -v exit
|
||||
@done_validating = false
|
||||
|
@ -61,7 +60,7 @@ module Mongrel
|
|||
# I need to add my own -v definition to prevent the -v from exiting by default as well.
|
||||
@opt.on_tail("--version", "Show version") do
|
||||
@done_validating = true
|
||||
puts "Version #{Mongrel::Const::MONGREL_VERSION}"
|
||||
puts "Version #{Puma::Const::PUMA_VERSION}"
|
||||
end
|
||||
|
||||
@opt.parse! argv
|
||||
|
@ -153,10 +152,10 @@ module Mongrel
|
|||
|
||||
# Prints a list of available commands.
|
||||
def print_command_list
|
||||
puts "#{Mongrel::Command::BANNER}\nAvailable commands are:\n\n"
|
||||
puts "#{Puma::Command::BANNER}\nAvailable commands are:\n\n"
|
||||
|
||||
self.commands.each do |name|
|
||||
if /mongrel::/ =~ name
|
||||
if /puma::/ =~ name
|
||||
name = name[9 .. -1]
|
||||
end
|
||||
|
||||
|
@ -178,14 +177,14 @@ module Mongrel
|
|||
print_command_list
|
||||
return true
|
||||
elsif cmd_name == "--version"
|
||||
puts "Mongrel Web Server #{Mongrel::Const::MONGREL_VERSION}"
|
||||
puts "Puma Web Server #{Puma::Const::PUMA_VERSION}"
|
||||
return true
|
||||
end
|
||||
|
||||
begin
|
||||
# quick hack so that existing commands will keep working but the Mongrel:: ones can be moved
|
||||
# quick hack so that existing commands will keep working but the Puma:: ones can be moved
|
||||
if ["start", "stop", "restart"].include? cmd_name
|
||||
cmd_name = "mongrel::" + cmd_name
|
||||
cmd_name = "puma::" + cmd_name
|
||||
end
|
||||
|
||||
command = GemPlugin::Manager.instance.create("/commands/#{cmd_name}", :argv => args)
|
||||
|
@ -204,7 +203,7 @@ module Mongrel
|
|||
# needed so the command is already valid so we can skip it.
|
||||
if not command.done_validating
|
||||
if not command.validate
|
||||
STDERR.puts "#{cmd_name} reported an error. Use mongrel_rails #{cmd_name} -h to get help."
|
||||
STDERR.puts "#{cmd_name} reported an error. Use puma_rails #{cmd_name} -h to get help."
|
||||
return false
|
||||
else
|
||||
command.run
|
|
@ -1,18 +1,18 @@
|
|||
require 'yaml'
|
||||
require 'etc'
|
||||
|
||||
module Mongrel
|
||||
# Implements a simple DSL for configuring a Mongrel server for your
|
||||
# purposes. More used by framework implementers to setup Mongrel
|
||||
module Puma
|
||||
# Implements a simple DSL for configuring a Puma server for your
|
||||
# purposes. More used by framework implementers to setup Puma
|
||||
# how they like, but could be used by regular folks to add more things
|
||||
# to an existing mongrel configuration.
|
||||
# to an existing puma configuration.
|
||||
#
|
||||
# It is used like this:
|
||||
#
|
||||
# require 'mongrel'
|
||||
# config = Mongrel::Configurator.new :host => "127.0.0.1" do
|
||||
# require 'puma'
|
||||
# config = Puma::Configurator.new :host => "127.0.0.1" do
|
||||
# listener :port => 3000 do
|
||||
# uri "/app", :handler => Mongrel::DirHandler.new(".", load_mime_map("mime.yaml"))
|
||||
# uri "/app", :handler => Puma::DirHandler.new(".", load_mime_map("mime.yaml"))
|
||||
# end
|
||||
# run
|
||||
# end
|
||||
|
@ -22,7 +22,7 @@ module Mongrel
|
|||
# specific to the servers but just a hash of default parameters that all
|
||||
# server or uri calls receive.
|
||||
#
|
||||
# When you are inside the block after Mongrel::Configurator.new you can simply
|
||||
# When you are inside the block after Puma::Configurator.new you can simply
|
||||
# call functions that are part of Configurator (like server, uri, daemonize, etc)
|
||||
# without having to refer to anything else. You can also call these functions on
|
||||
# the resulting object directly for additional configuration.
|
||||
|
@ -70,7 +70,7 @@ module Mongrel
|
|||
end
|
||||
rescue Errno::EPERM => e
|
||||
log "Couldn't change user and group to #{user.inspect}:#{group.inspect}: #{e.to_s}."
|
||||
log "Mongrel failed to start."
|
||||
log "Puma failed to start."
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
@ -136,7 +136,7 @@ module Mongrel
|
|||
ops[:throttle] ||= 0
|
||||
ops[:timeout] ||= 60
|
||||
|
||||
@listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:throttle].to_i, ops[:timeout].to_i)
|
||||
@listener = Puma::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:throttle].to_i, ops[:timeout].to_i)
|
||||
@listener_name = "#{ops[:host]}:#{ops[:port]}"
|
||||
@listeners[@listener_name] = @listener
|
||||
|
||||
|
@ -239,10 +239,10 @@ module Mongrel
|
|||
|
||||
|
||||
# Loads the MIME map file and checks that it is correct
|
||||
# on loading. This is commonly passed to Mongrel::DirHandler
|
||||
# on loading. This is commonly passed to Puma::DirHandler
|
||||
# or any framework handler that uses DirHandler to serve files.
|
||||
# You can also include a set of default MIME types as additional
|
||||
# settings. See Mongrel::DirHandler for how the MIME types map
|
||||
# settings. See Puma::DirHandler for how the MIME types map
|
||||
# is organized.
|
||||
def load_mime_map(file, mime={})
|
||||
# configure any requested mime map
|
||||
|
@ -263,7 +263,7 @@ module Mongrel
|
|||
GemPlugin::Manager.instance.create(name, ops)
|
||||
end
|
||||
|
||||
# Lets you do redirects easily as described in Mongrel::RedirectHandler.
|
||||
# Lets you do redirects easily as described in Puma::RedirectHandler.
|
||||
# You use it inside the configurator like this:
|
||||
#
|
||||
# redirect("/test", "/to/there") # simple
|
||||
|
@ -271,7 +271,7 @@ module Mongrel
|
|||
# redirect("/hey", /(w+)/) {|match| ...} # block
|
||||
#
|
||||
def redirect(from, pattern, replacement = nil, &block)
|
||||
uri from, :handler => Mongrel::RedirectHandler.new(pattern, replacement, &block)
|
||||
uri from, :handler => Puma::RedirectHandler.new(pattern, replacement, &block)
|
||||
end
|
||||
|
||||
# Works like a meta run method which goes through all the
|
||||
|
@ -282,7 +282,7 @@ module Mongrel
|
|||
s.run
|
||||
}
|
||||
|
||||
$mongrel_sleeper_thread = Thread.new { loop { sleep 1 } }
|
||||
$puma_sleeper_thread = Thread.new { loop { sleep 1 } }
|
||||
end
|
||||
|
||||
# Calls .stop on all the configured listeners so they
|
||||
|
@ -315,12 +315,12 @@ module Mongrel
|
|||
#
|
||||
# debug "/", what = [:rails]
|
||||
#
|
||||
# And it will only produce the log/mongrel_debug/rails.log file.
|
||||
# And it will only produce the log/puma_debug/rails.log file.
|
||||
# Available options are: :access, :files, :objects, :threads, :rails
|
||||
#
|
||||
# NOTE: Use [:files] to get accesses dumped to stderr like with WEBrick.
|
||||
def debug(location, what = [:access, :files, :objects, :threads, :rails])
|
||||
require 'mongrel/debug'
|
||||
require 'puma/debug'
|
||||
handlers = {
|
||||
:access => "/handlers/requestlog::access",
|
||||
:files => "/handlers/requestlog::files",
|
||||
|
@ -330,11 +330,11 @@ module Mongrel
|
|||
}
|
||||
|
||||
# turn on the debugging infrastructure, and ObjectTracker is a pig
|
||||
MongrelDbg.configure
|
||||
PumaDbg.configure
|
||||
|
||||
# now we roll through each requested debug type, turn it on and load that plugin
|
||||
what.each do |type|
|
||||
MongrelDbg.begin_trace type
|
||||
PumaDbg.begin_trace type
|
||||
uri location, :handler => plugin(handlers[type])
|
||||
end
|
||||
end
|
||||
|
@ -352,7 +352,7 @@ module Mongrel
|
|||
# a HUP signal since this is typically framework specific.
|
||||
#
|
||||
# Requires a :pid_file option given to Configurator.new to indicate a file to delete.
|
||||
# It sets the MongrelConfig.needs_restart attribute if
|
||||
# It sets the PumaConfig.needs_restart attribute if
|
||||
# the start command should reload. It's up to you to detect this
|
||||
# and do whatever is needed for a "restart".
|
||||
#
|
||||
|
@ -369,7 +369,7 @@ module Mongrel
|
|||
unless RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
|
||||
# graceful shutdown
|
||||
trap("TERM") { log "TERM signal received."; stop }
|
||||
trap("USR1") { log "USR1 received, toggling $mongrel_debug_client to #{!$mongrel_debug_client}"; $mongrel_debug_client = !$mongrel_debug_client }
|
||||
trap("USR1") { log "USR1 received, toggling $puma_debug_client to #{!$puma_debug_client}"; $puma_debug_client = !$puma_debug_client }
|
||||
# restart
|
||||
trap("USR2") { log "USR2 signal received."; stop(true) }
|
||||
|
||||
|
@ -379,7 +379,7 @@ module Mongrel
|
|||
end
|
||||
end
|
||||
|
||||
# Logs a simple message to STDERR (or the mongrel log if in daemon mode).
|
||||
# Logs a simple message to STDERR (or the puma log if in daemon mode).
|
||||
def log(msg)
|
||||
STDERR.print "** ", msg, "\n"
|
||||
end
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
module Mongrel
|
||||
module Puma
|
||||
|
||||
# Every standard HTTP code mapped to the appropriate message. These are
|
||||
# used so frequently that they are placed directly in Mongrel for easy
|
||||
# access rather than Mongrel::Const itself.
|
||||
# used so frequently that they are placed directly in Puma for easy
|
||||
# access rather than Puma::Const itself.
|
||||
HTTP_STATUS_CODES = {
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
|
@ -49,7 +49,7 @@ module Mongrel
|
|||
# gave about a 3% to 10% performance improvement over using the strings directly.
|
||||
# Symbols did not really improve things much compared to constants.
|
||||
#
|
||||
# While Mongrel does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
|
||||
# While Puma does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
|
||||
# REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
|
||||
# too taxing on performance.
|
||||
module Const
|
||||
|
@ -65,12 +65,12 @@ module Mongrel
|
|||
REQUEST_URI='REQUEST_URI'.freeze
|
||||
REQUEST_PATH='REQUEST_PATH'.freeze
|
||||
|
||||
MONGREL_VERSION = VERSION = "1.3.0".freeze
|
||||
PUMA_VERSION = VERSION = "1.3.0".freeze
|
||||
|
||||
MONGREL_TMP_BASE="mongrel".freeze
|
||||
PUMA_TMP_BASE="puma".freeze
|
||||
|
||||
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
||||
ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Mongrel #{MONGREL_VERSION}\r\n\r\nNOT FOUND".freeze
|
||||
ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze
|
||||
|
||||
CONTENT_LENGTH="CONTENT_LENGTH".freeze
|
||||
|
|
@ -1,22 +1,20 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'logger'
|
||||
require 'set'
|
||||
require 'socket'
|
||||
require 'fileutils'
|
||||
|
||||
module MongrelDbg
|
||||
module PumaDbg
|
||||
SETTINGS = { :tracing => {}}
|
||||
LOGGING = { }
|
||||
|
||||
def MongrelDbg::configure(log_dir = File.join("log","mongrel_debug"))
|
||||
def PumaDbg::configure(log_dir = File.join("log","puma_debug"))
|
||||
FileUtils.mkdir_p(log_dir)
|
||||
@log_dir = log_dir
|
||||
$objects_out=open(File.join("log","mongrel_debug","objects.log"),"w")
|
||||
$objects_out=open(File.join("log","puma_debug","objects.log"),"w")
|
||||
$objects_out.puts "run,classname,last,count,delta,lenmean,lensd,lenmax"
|
||||
$objects_out.sync = true
|
||||
$last_stat = nil
|
||||
|
@ -24,28 +22,28 @@ module MongrelDbg
|
|||
end
|
||||
|
||||
|
||||
def MongrelDbg::trace(target, message)
|
||||
def PumaDbg::trace(target, message)
|
||||
if SETTINGS[:tracing][target] and LOGGING[target]
|
||||
LOGGING[target].log(Logger::DEBUG, message)
|
||||
end
|
||||
end
|
||||
|
||||
def MongrelDbg::begin_trace(target)
|
||||
def PumaDbg::begin_trace(target)
|
||||
SETTINGS[:tracing][target] = true
|
||||
if not LOGGING[target]
|
||||
LOGGING[target] = Logger.new(File.join(@log_dir, "#{target.to_s}.log"))
|
||||
end
|
||||
MongrelDbg::trace(target, "TRACING ON #{Time.now}")
|
||||
PumaDbg::trace(target, "TRACING ON #{Time.now}")
|
||||
end
|
||||
|
||||
def MongrelDbg::end_trace(target)
|
||||
def PumaDbg::end_trace(target)
|
||||
SETTINGS[:tracing][target] = false
|
||||
MongrelDbg::trace(target, "TRACING OFF #{Time.now}")
|
||||
PumaDbg::trace(target, "TRACING OFF #{Time.now}")
|
||||
LOGGING[target].close
|
||||
LOGGING[target] = nil
|
||||
end
|
||||
|
||||
def MongrelDbg::tracing?(target)
|
||||
def PumaDbg::tracing?(target)
|
||||
SETTINGS[:tracing][target]
|
||||
end
|
||||
end
|
||||
|
@ -84,7 +82,7 @@ module Kernel
|
|||
open_counts[args] ||= 0
|
||||
open_counts[args] += 1
|
||||
end
|
||||
MongrelDbg::trace(:files, open_counts.to_yaml)
|
||||
PumaDbg::trace(:files, open_counts.to_yaml)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -92,10 +90,10 @@ end
|
|||
|
||||
module RequestLog
|
||||
|
||||
# Just logs whatever requests it gets to STDERR (which ends up in the mongrel
|
||||
# Just logs whatever requests it gets to STDERR (which ends up in the puma
|
||||
# log when daemonized).
|
||||
class Access < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request,response)
|
||||
p = request.params
|
||||
|
@ -105,10 +103,10 @@ module RequestLog
|
|||
|
||||
|
||||
class Files < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request, response)
|
||||
MongrelDbg::trace(:files, "#{Time.now} FILES OPEN BEFORE REQUEST #{request.params['PATH_INFO']}")
|
||||
PumaDbg::trace(:files, "#{Time.now} FILES OPEN BEFORE REQUEST #{request.params['PATH_INFO']}")
|
||||
log_open_files
|
||||
end
|
||||
|
||||
|
@ -116,7 +114,7 @@ module RequestLog
|
|||
|
||||
# stolen from Robert Klemme
|
||||
class Objects < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request,response)
|
||||
begin
|
||||
|
@ -127,7 +125,7 @@ module RequestLog
|
|||
begin
|
||||
if o.respond_to? :length
|
||||
len = o.length
|
||||
lengths[o.class] ||= Mongrel::Stats.new(o.class)
|
||||
lengths[o.class] ||= Puma::Stats.new(o.class)
|
||||
lengths[o.class].sample(len)
|
||||
end
|
||||
rescue Object
|
||||
|
@ -160,24 +158,24 @@ module RequestLog
|
|||
end
|
||||
|
||||
class Params < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request, response)
|
||||
MongrelDbg::trace(:rails, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
||||
MongrelDbg::trace(:rails, request.params.to_yaml)
|
||||
PumaDbg::trace(:rails, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
||||
PumaDbg::trace(:rails, request.params.to_yaml)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Threads < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request, response)
|
||||
MongrelDbg::trace(:threads, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
||||
PumaDbg::trace(:threads, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
||||
begin
|
||||
ObjectSpace.each_object do |obj|
|
||||
begin
|
||||
if obj.class == Mongrel::HttpServer
|
||||
if obj.class == Puma::HttpServer
|
||||
worker_list = obj.workers.list
|
||||
|
||||
if worker_list.length > 0
|
||||
|
@ -185,7 +183,7 @@ module RequestLog
|
|||
worker_list.each {|t| keys << "\n\t\t-- #{t}: #{t.keys.inspect}" }
|
||||
end
|
||||
|
||||
MongrelDbg::trace(:threads, "#{obj.host}:#{obj.port} -- THREADS: #{worker_list.length} #{keys}")
|
||||
PumaDbg::trace(:threads, "#{obj.host}:#{obj.port} -- THREADS: #{worker_list.length} #{keys}")
|
||||
end
|
||||
rescue Object # Ignore since obj.class can sometimes take parameters
|
||||
end
|
||||
|
@ -198,6 +196,6 @@ end
|
|||
|
||||
|
||||
END {
|
||||
MongrelDbg::trace(:files, "FILES OPEN AT EXIT")
|
||||
PumaDbg::trace(:files, "FILES OPEN AT EXIT")
|
||||
log_open_files
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
module Mongrel
|
||||
module Puma
|
||||
module Gems
|
||||
class << self
|
||||
|
||||
|
@ -12,11 +12,11 @@ module Mongrel
|
|||
version ? gem(library, version) : gem(library)
|
||||
retry
|
||||
rescue Gem::LoadError, LoadError, RuntimeError
|
||||
# puts "** #{library.inspect} could not be loaded" unless library == "mongrel_experimental"
|
||||
# puts "** #{library.inspect} could not be loaded" unless library == "puma_experimental"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,14 +1,12 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'mongrel/stats'
|
||||
require 'puma/stats'
|
||||
require 'zlib'
|
||||
require 'yaml'
|
||||
|
||||
module Mongrel
|
||||
module Puma
|
||||
|
||||
# You implement your application handler with this. It's very light giving
|
||||
# just the minimum necessary for you to handle a request and shoot back
|
||||
|
@ -23,15 +21,15 @@ module Mongrel
|
|||
attr_reader :request_notify
|
||||
attr_accessor :listener
|
||||
|
||||
# This will be called by Mongrel if HttpHandler.request_notify set to *true*.
|
||||
# This will be called by Puma if HttpHandler.request_notify set to *true*.
|
||||
# You only get the parameters for the request, with the idea that you'd "bound"
|
||||
# the beginning of the request processing and the first call to process.
|
||||
def request_begins(params)
|
||||
end
|
||||
|
||||
# Called by Mongrel for each IO chunk that is received on the request socket
|
||||
# Called by Puma for each IO chunk that is received on the request socket
|
||||
# from the client, allowing you to track the progress of the IO and monitor
|
||||
# the input. This will be called by Mongrel only if HttpHandler.request_notify
|
||||
# the input. This will be called by Puma only if HttpHandler.request_notify
|
||||
# set to *true*.
|
||||
def request_progress(params, clen, total)
|
||||
end
|
||||
|
@ -280,7 +278,7 @@ module Mongrel
|
|||
end
|
||||
|
||||
|
||||
# When added to a config script (-S in mongrel_rails) it will
|
||||
# When added to a config script (-S in puma_rails) it will
|
||||
# look at the client's allowed response types and then gzip
|
||||
# compress anything that is going out.
|
||||
#
|
||||
|
@ -341,11 +339,11 @@ module Mongrel
|
|||
def initialize(ops={})
|
||||
@sample_rate = ops[:sample_rate] || 300
|
||||
|
||||
@processors = Mongrel::Stats.new("processors")
|
||||
@reqsize = Mongrel::Stats.new("request Kb")
|
||||
@headcount = Mongrel::Stats.new("req param count")
|
||||
@respsize = Mongrel::Stats.new("response Kb")
|
||||
@interreq = Mongrel::Stats.new("inter-request time")
|
||||
@processors = Puma::Stats.new("processors")
|
||||
@reqsize = Puma::Stats.new("request Kb")
|
||||
@headcount = Puma::Stats.new("req param count")
|
||||
@respsize = Puma::Stats.new("response Kb")
|
||||
@interreq = Puma::Stats.new("inter-request time")
|
||||
end
|
||||
|
||||
|
||||
|
@ -365,7 +363,7 @@ module Mongrel
|
|||
|
||||
|
||||
# The :stats_filter is basically any configured stats filter that you've added to this same
|
||||
# URI. This lets the status handler print out statistics on how Mongrel is doing.
|
||||
# URI. This lets the status handler print out statistics on how Puma is doing.
|
||||
class StatusHandler < HttpHandler
|
||||
def initialize(ops={})
|
||||
@stats = ops[:stats_filter]
|
||||
|
@ -413,7 +411,7 @@ module Mongrel
|
|||
def process(request, response)
|
||||
response.start do |head,out|
|
||||
out.write <<-END
|
||||
<html><body><title>Mongrel Server Status</title>
|
||||
<html><body><title>Puma Server Status</title>
|
||||
#{describe_listener}
|
||||
</body></html>
|
||||
END
|
||||
|
@ -429,13 +427,13 @@ module Mongrel
|
|||
#
|
||||
# == Examples
|
||||
#
|
||||
# h = Mongrel::HttpServer.new('0.0.0.0')
|
||||
# h.register '/test', Mongrel::RedirectHandler.new('/to/there') # simple
|
||||
# h.register '/to', Mongrel::RedirectHandler.new(/t/, 'w') # regexp
|
||||
# h = Puma::HttpServer.new('0.0.0.0')
|
||||
# h.register '/test', Puma::RedirectHandler.new('/to/there') # simple
|
||||
# h.register '/to', Puma::RedirectHandler.new(/t/, 'w') # regexp
|
||||
# # and with a block
|
||||
# h.register '/hey', Mongrel::RedirectHandler.new(/(\w+)/) { |match| ... }
|
||||
# h.register '/hey', Puma::RedirectHandler.new(/(\w+)/) { |match| ... }
|
||||
#
|
||||
class RedirectHandler < Mongrel::HttpHandler
|
||||
class RedirectHandler < Puma::HttpHandler
|
||||
# You set the rewrite rules when building the object.
|
||||
#
|
||||
# pattern => What to look for or replacement if used alone
|
||||
|
@ -453,14 +451,14 @@ module Mongrel
|
|||
# Process the request and return a redirect response
|
||||
def process(request, response)
|
||||
unless @pattern
|
||||
response.socket.write(Mongrel::Const::REDIRECT % @replacement)
|
||||
response.socket.write(Puma::Const::REDIRECT % @replacement)
|
||||
else
|
||||
if @block
|
||||
new_path = request.params['REQUEST_URI'].gsub(@pattern, &@block)
|
||||
else
|
||||
new_path = request.params['REQUEST_URI'].gsub(@pattern, @replacement)
|
||||
end
|
||||
response.socket.write(Mongrel::Const::REDIRECT % new_path)
|
||||
response.socket.write(Puma::Const::REDIRECT % new_path)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
module Mongrel
|
||||
module Puma
|
||||
# This class implements a simple way of constructing the HTTP headers
|
||||
# dynamically via a Hash syntax. Think of it as a write-only Hash.
|
||||
# Refer to HttpResponse for information on how this is used.
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
module Mongrel
|
||||
module Puma
|
||||
#
|
||||
# When a handler is found for a registered URI then this class is constructed
|
||||
# and passed to your HttpHandler::process method. You should assume that
|
||||
|
@ -37,7 +37,7 @@ module Mongrel
|
|||
# must read more data to complete body
|
||||
if remain > Const::MAX_BODY
|
||||
# huge body, put it in a tempfile
|
||||
@body = Tempfile.new(Const::MONGREL_TMP_BASE)
|
||||
@body = Tempfile.new(Const::PUMA_TMP_BASE)
|
||||
@body.binmode
|
||||
else
|
||||
# small body, just use that
|
|
@ -1,4 +1,4 @@
|
|||
module Mongrel
|
||||
module Puma
|
||||
# Writes and controls your response to the client using the HTTP/1.1 specification.
|
||||
# You use it by simply doing:
|
||||
#
|
||||
|
@ -7,7 +7,7 @@ module Mongrel
|
|||
# out.write("hello\n")
|
||||
# end
|
||||
#
|
||||
# The parameter to start is the response code--which Mongrel will translate for you
|
||||
# The parameter to start is the response code--which Puma will translate for you
|
||||
# based on HTTP_STATUS_CODES. The head parameter is how you write custom headers.
|
||||
# The out parameter is where you write your body. The default status code for
|
||||
# HttpResponse.start is 200 so the above example is redundant.
|
||||
|
@ -57,7 +57,7 @@ module Mongrel
|
|||
# body content as needed. Handlers are able to modify pretty much
|
||||
# any part of the request in the chain, and can stop further processing
|
||||
# by simple passing "finalize=true" to the start method. By default
|
||||
# all handlers run and then mongrel finalizes the request when they're
|
||||
# all handlers run and then puma finalizes the request when they're
|
||||
# all done.
|
||||
def start(status=200, finalize=false, reason=nil)
|
||||
@status = status.to_i
|
||||
|
@ -75,7 +75,6 @@ module Mongrel
|
|||
elsif @header_sent
|
||||
raise "You have already sent the request headers."
|
||||
else
|
||||
# XXX Dubious ( http://mongrel.rubyforge.org/ticket/19 )
|
||||
@header.out.close
|
||||
@header = HeaderOut.new(StringIO.new)
|
||||
|
8
lib/puma/init.rb
Normal file
8
lib/puma/init.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
|
||||
require 'puma/gems'
|
||||
Puma::Gems.require 'gem_plugin'
|
||||
|
||||
# File is just a stub that makes sure the puma_plugins gem is loaded and ready
|
|
@ -1,12 +1,12 @@
|
|||
require 'rack'
|
||||
require 'mongrel/thread_pool'
|
||||
require 'puma/thread_pool'
|
||||
|
||||
module Mongrel
|
||||
module Puma
|
||||
# Thrown at a thread when it is timed out.
|
||||
class TimeoutError < RuntimeError; end
|
||||
|
||||
# This is the main driver of Mongrel, while the Mongrel::HttpParser and
|
||||
# Mongrel::URIClassifier make up the majority of how the server functions.
|
||||
# This is the main driver of Puma, while the Puma::HttpParser and
|
||||
# Puma::URIClassifier make up the majority of how the server functions.
|
||||
# It's a very simple class that just has a thread accepting connections and
|
||||
# a simple HttpServer.process_client function to do the heavy lifting with
|
||||
# the IO and Ruby.
|
||||
|
@ -22,13 +22,13 @@ module Mongrel
|
|||
#
|
||||
# Ruby's thread implementation is "interesting" to say the least.
|
||||
# Experiments with *many* different types of IO processing simply cannot
|
||||
# make a dent in it. Future releases of Mongrel will find other creative
|
||||
# make a dent in it. Future releases of Puma will find other creative
|
||||
# ways to make threads faster, but don't hold your breath until Ruby 1.9
|
||||
# is actually finally useful.
|
||||
|
||||
class Server
|
||||
|
||||
include Mongrel::Const
|
||||
include Puma::Const
|
||||
|
||||
attr_reader :acceptor
|
||||
attr_reader :workers
|
||||
|
@ -81,7 +81,7 @@ module Mongrel
|
|||
end
|
||||
|
||||
params[SERVER_PROTOCOL] = HTTP_11
|
||||
params[SERVER_SOFTWARE] = MONGREL_VERSION
|
||||
params[SERVER_SOFTWARE] = PUMA_VERSION
|
||||
params[GATEWAY_INTERFACE] = CGI_VER
|
||||
|
||||
unless params[REQUEST_PATH]
|
||||
|
@ -317,7 +317,7 @@ module Mongrel
|
|||
# Simply registers a handler with the internal URIClassifier.
|
||||
# When the URI is found in the prefix of a request then your handler's
|
||||
# HttpHandler::process method is called.
|
||||
# See Mongrel::URIClassifier#register for more information.
|
||||
# See Puma::URIClassifier#register for more information.
|
||||
#
|
||||
# If you set in_front=true then the passed in handler will be put in
|
||||
# the front of the list for that particular URI. Otherwise it's placed
|
||||
|
@ -338,7 +338,7 @@ module Mongrel
|
|||
handler.listener = self
|
||||
end
|
||||
|
||||
# Removes any handlers registered at the given URI. See Mongrel::URIClassifier#unregister
|
||||
# Removes any handlers registered at the given URI. See Puma::URIClassifier#unregister
|
||||
# for more information. Remember this removes them *all* so the entire
|
||||
# processing chain goes away.
|
||||
def unregister(uri)
|
|
@ -1,9 +1,6 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
# A very simple little class for doing some basic fast statistics sampling.
|
||||
# You feed it either samples of numeric data you want measured or you call
|
||||
# Stats.tick to get it to add a time delta between the last time you called it.
|
||||
|
@ -12,7 +9,7 @@
|
|||
#
|
||||
# It does all of this very fast and doesn't take up any memory since the samples
|
||||
# are not stored but instead all the values are calculated on the fly.
|
||||
module Mongrel
|
||||
module Puma
|
||||
class Stats
|
||||
attr_reader :sum, :sumsq, :n, :min, :max
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
|
||||
# A modification proposed by Sean Treadway that increases the default accept
|
|
@ -1,6 +1,6 @@
|
|||
require 'thread'
|
||||
|
||||
module Mongrel
|
||||
module Puma
|
||||
class ThreadPool
|
||||
def initialize(min, max, &blk)
|
||||
@todo = Queue.new
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
module Mongrel
|
||||
module Puma
|
||||
class URIClassifier
|
||||
|
||||
class RegistrationError < RuntimeError
|
|
@ -1,13 +1,11 @@
|
|||
require 'hoe'
|
||||
|
||||
HOE = Hoe.spec 'mongrel' do
|
||||
self.rubyforge_name = 'mongrel'
|
||||
developer 'Zed A. Shaw', 'mongrel-users@rubyforge.org'
|
||||
|
||||
spec_extras[:required_ruby_version] = Gem::Requirement.new('>= 1.8.6')
|
||||
HOE = Hoe.spec 'puma' do
|
||||
self.rubyforge_name = 'puma'
|
||||
developer 'Evan Phoenix', 'evan@phx.io'
|
||||
|
||||
spec_extras[:extensions] = ["ext/http11/extconf.rb"]
|
||||
spec_extras[:executables] = ['mongrel_rails']
|
||||
spec_extras[:executables] = ['puma_rails']
|
||||
|
||||
extra_rdoc_files << 'LICENSE'
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ file 'ext/http11/http11_parser.c' => ['ext/http11/http11_parser.rl'] do |t|
|
|||
end
|
||||
end
|
||||
|
||||
file 'ext/http11/org/jruby/mongrel/Http11Parser.java' => ['ext/http11/http11_parser.java.rl'] do |t|
|
||||
file 'ext/http11/org/jruby/puma/Http11Parser.java' => ['ext/http11/http11_parser.java.rl'] do |t|
|
||||
begin
|
||||
sh "ragel #{t.prerequisites.last} -J -G2 -o #{t.name}"
|
||||
rescue
|
||||
|
@ -17,4 +17,4 @@ file 'ext/http11/org/jruby/mongrel/Http11Parser.java' => ['ext/http11/http11_par
|
|||
end
|
||||
end
|
||||
|
||||
task :ragel => (defined?(JRUBY_VERSION) ? 'ext/http11/org/jruby/mongrel/Http11Parser.java' : 'ext/http11/http11_parser.c')
|
||||
task :ragel => (defined?(JRUBY_VERSION) ? 'ext/http11/org/jruby/puma/Http11Parser.java' : 'ext/http11/http11_parser.c')
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
uri "/fromconf", :handler => Mongrel::Error404Handler.new("test")
|
1
test/puma.conf
Normal file
1
test/puma.conf
Normal file
|
@ -0,0 +1 @@
|
|||
uri "/fromconf", :handler => Puma::Error404Handler.new("test")
|
|
@ -7,7 +7,7 @@
|
|||
require 'test/testhelp'
|
||||
|
||||
class TestCommand < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
include Puma::Command::Base
|
||||
|
||||
def configure
|
||||
options [
|
||||
|
@ -47,7 +47,7 @@ class CommandTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def run_cmd(args)
|
||||
Mongrel::Command::Registry.instance.run args
|
||||
Puma::Command::Registry.instance.run args
|
||||
end
|
||||
|
||||
def test_run_command
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
include Mongrel
|
||||
include Puma
|
||||
|
||||
class ConditionalResponseTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@server = HttpServer.new('127.0.0.1', 3501)
|
||||
@server.register('/', Mongrel::DirHandler.new('.'))
|
||||
@server.register('/', Puma::DirHandler.new('.'))
|
||||
@server.run
|
||||
|
||||
@http = Net::HTTP.new(@server.host, @server.port)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# Additional work donated by contributors. See http://puma.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'test/testhelp'
|
||||
|
@ -9,7 +9,7 @@ require 'test/testhelp'
|
|||
$test_plugin_fired = 0
|
||||
|
||||
class TestPlugin < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request, response)
|
||||
$test_plugin_fired += 1
|
||||
|
@ -18,7 +18,7 @@ end
|
|||
|
||||
|
||||
class Sentinel < GemPlugin::Plugin "/handlers"
|
||||
include Mongrel::HttpHandlerPlugin
|
||||
include Puma::HttpHandlerPlugin
|
||||
|
||||
def process(request, response)
|
||||
raise "This Sentinel plugin shouldn't run."
|
||||
|
@ -32,23 +32,23 @@ class ConfiguratorTest < Test::Unit::TestCase
|
|||
@config = nil
|
||||
|
||||
redirect_test_io do
|
||||
@config = Mongrel::Configurator.new :host => "localhost" do
|
||||
@config = Puma::Configurator.new :host => "localhost" do
|
||||
listener :port => 4501 do
|
||||
# 2 in front should run, but the sentinel shouldn't since dirhandler processes the request
|
||||
uri "/", :handler => plugin("/handlers/testplugin")
|
||||
uri "/", :handler => plugin("/handlers/testplugin")
|
||||
uri "/", :handler => Mongrel::DirHandler.new(".")
|
||||
uri "/", :handler => Puma::DirHandler.new(".")
|
||||
uri "/", :handler => plugin("/handlers/testplugin")
|
||||
|
||||
uri "/test", :handler => plugin("/handlers/testplugin")
|
||||
uri "/test", :handler => plugin("/handlers/testplugin")
|
||||
uri "/test", :handler => Mongrel::DirHandler.new(".")
|
||||
uri "/test", :handler => Puma::DirHandler.new(".")
|
||||
uri "/test", :handler => plugin("/handlers/testplugin")
|
||||
|
||||
debug "/"
|
||||
setup_signals
|
||||
|
||||
run_config(File.dirname(__FILE__) + "/../test/mongrel.conf")
|
||||
run_config(File.dirname(__FILE__) + "/../test/puma.conf")
|
||||
load_mime_map(File.dirname(__FILE__) + "/../test/mime.yaml")
|
||||
|
||||
run
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# Additional work donated by contributors. See http://puma.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
require 'test/testhelp'
|
||||
require 'mongrel/debug'
|
||||
require 'puma/debug'
|
||||
|
||||
class MongrelDbgTest < Test::Unit::TestCase
|
||||
class PumaDbgTest < Test::Unit::TestCase
|
||||
|
||||
def test_tracing_to_log
|
||||
FileUtils.rm_rf "log/mongrel_debug"
|
||||
FileUtils.rm_rf "log/puma_debug"
|
||||
|
||||
MongrelDbg::configure
|
||||
PumaDbg::configure
|
||||
out = StringIO.new
|
||||
|
||||
MongrelDbg::begin_trace(:rails)
|
||||
MongrelDbg::trace(:rails, "Good stuff")
|
||||
MongrelDbg::end_trace(:rails)
|
||||
PumaDbg::begin_trace(:rails)
|
||||
PumaDbg::trace(:rails, "Good stuff")
|
||||
PumaDbg::end_trace(:rails)
|
||||
|
||||
assert File.exist?("log/mongrel_debug"), "Didn't make logging directory"
|
||||
assert File.exist?("log/puma_debug"), "Didn't make logging directory"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
class SimpleHandler < Mongrel::HttpHandler
|
||||
class SimpleHandler < Puma::HttpHandler
|
||||
def process(request, response)
|
||||
response.start do |head,out|
|
||||
head["Content-Type"] = "text/html"
|
||||
|
@ -16,7 +16,7 @@ class SimpleHandler < Mongrel::HttpHandler
|
|||
end
|
||||
end
|
||||
|
||||
class DumbHandler < Mongrel::HttpHandler
|
||||
class DumbHandler < Puma::HttpHandler
|
||||
def process(request, response)
|
||||
response.start do |head,out|
|
||||
head["Content-Type"] = "text/html"
|
||||
|
@ -34,19 +34,19 @@ end
|
|||
class HandlersTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
stats = Mongrel::StatisticsFilter.new(:sample_rate => 1)
|
||||
stats = Puma::StatisticsFilter.new(:sample_rate => 1)
|
||||
|
||||
@config = Mongrel::Configurator.new :host => '127.0.0.1', :port => 9998 do
|
||||
@config = Puma::Configurator.new :host => '127.0.0.1', :port => 9998 do
|
||||
listener do
|
||||
uri "/", :handler => SimpleHandler.new
|
||||
uri "/", :handler => stats
|
||||
uri "/404", :handler => Mongrel::Error404Handler.new("Not found")
|
||||
uri "/dumb", :handler => Mongrel::DeflateFilter.new
|
||||
uri "/404", :handler => Puma::Error404Handler.new("Not found")
|
||||
uri "/dumb", :handler => Puma::DeflateFilter.new
|
||||
uri "/dumb", :handler => DumbHandler.new, :in_front => true
|
||||
uri "/files", :handler => Mongrel::DirHandler.new("doc")
|
||||
uri "/files_nodir", :handler => Mongrel::DirHandler.new("doc", listing_allowed=false, index_html="none")
|
||||
uri "/status", :handler => Mongrel::StatusHandler.new(:stats_filter => stats)
|
||||
uri "/relative", :handler => Mongrel::DirHandler.new(nil, listing_allowed=false, index_html="none")
|
||||
uri "/files", :handler => Puma::DirHandler.new("doc")
|
||||
uri "/files_nodir", :handler => Puma::DirHandler.new("doc", listing_allowed=false, index_html="none")
|
||||
uri "/status", :handler => Puma::StatusHandler.new(:stats_filter => stats)
|
||||
uri "/relative", :handler => Puma::DirHandler.new(nil, listing_allowed=false, index_html="none")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,8 +63,8 @@ class HandlersTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_registration_exception_is_not_lost
|
||||
assert_raises(Mongrel::URIClassifier::RegistrationError) do
|
||||
@config = Mongrel::Configurator.new do
|
||||
assert_raises(Puma::URIClassifier::RegistrationError) do
|
||||
@config = Puma::Configurator.new do
|
||||
listener do
|
||||
uri "bogus", :handler => SimpleHandler.new
|
||||
end
|
||||
|
@ -89,7 +89,7 @@ class HandlersTest < Test::Unit::TestCase
|
|||
return if windows?
|
||||
|
||||
# Camping uses this internally
|
||||
handler = Mongrel::DirHandler.new(nil, false)
|
||||
handler = Puma::DirHandler.new(nil, false)
|
||||
assert handler.can_serve("/tmp/testfile")
|
||||
# Not a bug! A nil @file parameter is the only circumstance under which
|
||||
# we are allowed to serve any existing file
|
||||
|
@ -97,8 +97,8 @@ class HandlersTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_non_nil_dirhandler_is_not_vulnerable_to_path_traversal
|
||||
# The famous security bug of Mongrel 1.1.2
|
||||
handler = Mongrel::DirHandler.new("/doc", false)
|
||||
# The famous security bug of Puma 1.1.2
|
||||
handler = Puma::DirHandler.new("/doc", false)
|
||||
assert_nil handler.can_serve("/tmp/testfile")
|
||||
assert_nil handler.can_serve("../../../../../../../../../../tmp/testfile")
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
include Mongrel
|
||||
include Puma
|
||||
|
||||
class HttpParserTest < Test::Unit::TestCase
|
||||
|
||||
|
@ -100,7 +100,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|||
# then that large header names are caught
|
||||
10.times do |c|
|
||||
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
||||
assert_raises Mongrel::HttpParserError do
|
||||
assert_raises Puma::HttpParserError do
|
||||
parser.execute({}, get, 0)
|
||||
parser.reset
|
||||
end
|
||||
|
@ -109,7 +109,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|||
# then that large mangled field values are caught
|
||||
10.times do |c|
|
||||
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
||||
assert_raises Mongrel::HttpParserError do
|
||||
assert_raises Puma::HttpParserError do
|
||||
parser.execute({}, get, 0)
|
||||
parser.reset
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|||
# then large headers are rejected too
|
||||
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
||||
get << "X-Test: test\r\n" * (80 * 1024)
|
||||
assert_raises Mongrel::HttpParserError do
|
||||
assert_raises Puma::HttpParserError do
|
||||
parser.execute({}, get, 0)
|
||||
parser.reset
|
||||
end
|
||||
|
@ -126,7 +126,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|||
# finally just that random garbage gets blocked all the time
|
||||
10.times do |c|
|
||||
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
||||
assert_raises Mongrel::HttpParserError do
|
||||
assert_raises Puma::HttpParserError do
|
||||
parser.execute({}, get, 0)
|
||||
parser.reset
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require 'test/unit'
|
||||
require 'mongrel'
|
||||
require 'puma'
|
||||
require 'rack/lint'
|
||||
require 'test/testhelp'
|
||||
|
||||
|
@ -42,7 +42,7 @@ class TestRackServer < Test::Unit::TestCase
|
|||
def setup
|
||||
@valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
||||
|
||||
@server = Mongrel::RackServer.new("127.0.0.1", 9998)
|
||||
@server = Puma::RackServer.new("127.0.0.1", 9998)
|
||||
@simple = lambda { |env| [200, { "X-Header" => "Works" }, "Hello"] }
|
||||
@server.app = @simple
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ class RedirectHandlerTest < Test::Unit::TestCase
|
|||
|
||||
def setup
|
||||
redirect_test_io do
|
||||
@server = Mongrel::HttpServer.new('127.0.0.1', 9998)
|
||||
@server = Puma::HttpServer.new('127.0.0.1', 9998)
|
||||
end
|
||||
@server.run
|
||||
@client = Net::HTTP.new('127.0.0.1', 9998)
|
||||
|
@ -21,7 +21,7 @@ class RedirectHandlerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_simple_redirect
|
||||
tester = Mongrel::RedirectHandler.new('/yo')
|
||||
tester = Puma::RedirectHandler.new('/yo')
|
||||
@server.register("/test", tester)
|
||||
|
||||
sleep(1)
|
||||
|
@ -31,7 +31,7 @@ class RedirectHandlerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_rewrite
|
||||
tester = Mongrel::RedirectHandler.new(/(\w+)/, '+\1+')
|
||||
tester = Puma::RedirectHandler.new(/(\w+)/, '+\1+')
|
||||
@server.register("/test", tester)
|
||||
|
||||
sleep(1)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
include Mongrel
|
||||
include Puma
|
||||
|
||||
class ResponseTest < Test::Unit::TestCase
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ class StatsTest < Test::Unit::TestCase
|
|||
def test_sampling_speed
|
||||
out = StringIO.new
|
||||
|
||||
s = Mongrel::Stats.new("test")
|
||||
t = Mongrel::Stats.new("time")
|
||||
s = Puma::Stats.new("test")
|
||||
t = Puma::Stats.new("time")
|
||||
|
||||
100.times { s.sample(rand(20)); t.tick }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'test/unit'
|
||||
|
||||
require 'mongrel/thread_pool'
|
||||
require 'puma/thread_pool'
|
||||
|
||||
class TestThreadPool < Test::Unit::TestCase
|
||||
|
||||
|
@ -10,7 +10,7 @@ class TestThreadPool < Test::Unit::TestCase
|
|||
|
||||
def new_pool(min, max, &blk)
|
||||
blk = lambda { } unless blk
|
||||
@pool = Mongrel::ThreadPool.new(min, max, &blk)
|
||||
@pool = Puma::ThreadPool.new(min, max, &blk)
|
||||
end
|
||||
|
||||
def test_append_spawns
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
include Mongrel
|
||||
include Puma
|
||||
|
||||
class URIClassifierTest < Test::Unit::TestCase
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
require 'test/testhelp'
|
||||
|
||||
include Mongrel
|
||||
include Puma
|
||||
|
||||
class TestHandler < Mongrel::HttpHandler
|
||||
class TestHandler < Puma::HttpHandler
|
||||
attr_reader :ran_test
|
||||
|
||||
def process(request, response)
|
||||
|
@ -92,9 +92,9 @@ class WebServerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_file_streamed_request
|
||||
body = "a" * (Mongrel::Const::MAX_BODY * 2)
|
||||
body = "a" * (Puma::Const::MAX_BODY * 2)
|
||||
long = "GET /test HTTP/1.1\r\nContent-length: #{body.length}\r\n\r\n" + body
|
||||
do_test(long, Mongrel::Const::CHUNK_SIZE * 2 -400)
|
||||
do_test(long, Puma::Const::CHUNK_SIZE * 2 -400)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2005 Zed A. Shaw
|
||||
# You can redistribute it and/or modify it under the same terms as Ruby.
|
||||
#
|
||||
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
||||
# Additional work donated by contributors. See http://puma.rubyforge.org/attributions.html
|
||||
# for more information.
|
||||
|
||||
|
||||
|
@ -22,8 +22,8 @@ require 'uri'
|
|||
require 'stringio'
|
||||
require 'pp'
|
||||
|
||||
require 'mongrel'
|
||||
require 'mongrel/stats'
|
||||
require 'puma'
|
||||
require 'puma/stats'
|
||||
|
||||
if ENV['DEBUG']
|
||||
require 'ruby-debug'
|
||||
|
|
Loading…
Add table
Reference in a new issue