puma-simon 3.7.1

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.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +20 -0
  3. data/.gitignore +18 -0
  4. data/.hoeignore +12 -0
  5. data/.travis.yml +29 -0
  6. data/DEPLOYMENT.md +91 -0
  7. data/Gemfile +12 -0
  8. data/History.md +1254 -0
  9. data/LICENSE +26 -0
  10. data/Manifest.txt +78 -0
  11. data/README.md +353 -0
  12. data/Rakefile +158 -0
  13. data/Release.md +9 -0
  14. data/bin/puma +10 -0
  15. data/bin/puma-wild +31 -0
  16. data/bin/pumactl +12 -0
  17. data/docs/nginx.md +80 -0
  18. data/docs/signals.md +43 -0
  19. data/docs/systemd.md +197 -0
  20. data/examples/CA/cacert.pem +23 -0
  21. data/examples/CA/newcerts/cert_1.pem +19 -0
  22. data/examples/CA/newcerts/cert_2.pem +19 -0
  23. data/examples/CA/private/cakeypair.pem +30 -0
  24. data/examples/CA/serial +1 -0
  25. data/examples/config.rb +200 -0
  26. data/examples/plugins/redis_stop_puma.rb +46 -0
  27. data/examples/puma/cert_puma.pem +19 -0
  28. data/examples/puma/client-certs/ca.crt +19 -0
  29. data/examples/puma/client-certs/ca.key +27 -0
  30. data/examples/puma/client-certs/client.crt +19 -0
  31. data/examples/puma/client-certs/client.key +27 -0
  32. data/examples/puma/client-certs/client_expired.crt +19 -0
  33. data/examples/puma/client-certs/client_expired.key +27 -0
  34. data/examples/puma/client-certs/client_unknown.crt +19 -0
  35. data/examples/puma/client-certs/client_unknown.key +27 -0
  36. data/examples/puma/client-certs/generate.rb +78 -0
  37. data/examples/puma/client-certs/keystore.jks +0 -0
  38. data/examples/puma/client-certs/server.crt +19 -0
  39. data/examples/puma/client-certs/server.key +27 -0
  40. data/examples/puma/client-certs/server.p12 +0 -0
  41. data/examples/puma/client-certs/unknown_ca.crt +19 -0
  42. data/examples/puma/client-certs/unknown_ca.key +27 -0
  43. data/examples/puma/csr_puma.pem +11 -0
  44. data/examples/puma/keystore.jks +0 -0
  45. data/examples/puma/puma_keypair.pem +15 -0
  46. data/examples/qc_config.rb +13 -0
  47. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  48. data/ext/puma_http11/ext_help.h +15 -0
  49. data/ext/puma_http11/extconf.rb +15 -0
  50. data/ext/puma_http11/http11_parser.c +1069 -0
  51. data/ext/puma_http11/http11_parser.h +65 -0
  52. data/ext/puma_http11/http11_parser.java.rl +161 -0
  53. data/ext/puma_http11/http11_parser.rl +147 -0
  54. data/ext/puma_http11/http11_parser_common.rl +54 -0
  55. data/ext/puma_http11/io_buffer.c +155 -0
  56. data/ext/puma_http11/mini_ssl.c +457 -0
  57. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  58. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +473 -0
  59. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +339 -0
  60. data/ext/puma_http11/puma_http11.c +500 -0
  61. data/gemfiles/2.1-Gemfile +12 -0
  62. data/lib/puma.rb +15 -0
  63. data/lib/puma/accept_nonblock.rb +23 -0
  64. data/lib/puma/app/status.rb +66 -0
  65. data/lib/puma/binder.rb +402 -0
  66. data/lib/puma/cli.rb +220 -0
  67. data/lib/puma/client.rb +434 -0
  68. data/lib/puma/cluster.rb +510 -0
  69. data/lib/puma/commonlogger.rb +106 -0
  70. data/lib/puma/compat.rb +14 -0
  71. data/lib/puma/configuration.rb +364 -0
  72. data/lib/puma/const.rb +224 -0
  73. data/lib/puma/control_cli.rb +259 -0
  74. data/lib/puma/convenient.rb +23 -0
  75. data/lib/puma/daemon_ext.rb +31 -0
  76. data/lib/puma/delegation.rb +11 -0
  77. data/lib/puma/detect.rb +13 -0
  78. data/lib/puma/dsl.rb +486 -0
  79. data/lib/puma/events.rb +152 -0
  80. data/lib/puma/io_buffer.rb +7 -0
  81. data/lib/puma/java_io_buffer.rb +45 -0
  82. data/lib/puma/jruby_restart.rb +83 -0
  83. data/lib/puma/launcher.rb +410 -0
  84. data/lib/puma/minissl.rb +221 -0
  85. data/lib/puma/null_io.rb +42 -0
  86. data/lib/puma/plugin.rb +115 -0
  87. data/lib/puma/plugin/tmp_restart.rb +35 -0
  88. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  89. data/lib/puma/rack/builder.rb +298 -0
  90. data/lib/puma/rack/urlmap.rb +91 -0
  91. data/lib/puma/rack_default.rb +7 -0
  92. data/lib/puma/reactor.rb +210 -0
  93. data/lib/puma/runner.rb +171 -0
  94. data/lib/puma/server.rb +949 -0
  95. data/lib/puma/single.rb +112 -0
  96. data/lib/puma/state_file.rb +29 -0
  97. data/lib/puma/tcp_logger.rb +39 -0
  98. data/lib/puma/thread_pool.rb +297 -0
  99. data/lib/puma/util.rb +128 -0
  100. data/lib/rack/handler/puma.rb +78 -0
  101. data/puma.gemspec +52 -0
  102. data/test/ab_rs.rb +22 -0
  103. data/test/config.rb +2 -0
  104. data/test/config/app.rb +9 -0
  105. data/test/config/plugin.rb +1 -0
  106. data/test/config/settings.rb +2 -0
  107. data/test/config/state_file_testing_config.rb +14 -0
  108. data/test/hello-bind.ru +2 -0
  109. data/test/hello-delay.ru +3 -0
  110. data/test/hello-map.ru +3 -0
  111. data/test/hello-post.ru +4 -0
  112. data/test/hello-stuck.ru +1 -0
  113. data/test/hello-tcp.ru +5 -0
  114. data/test/hello.ru +1 -0
  115. data/test/hijack.ru +6 -0
  116. data/test/hijack2.ru +5 -0
  117. data/test/lobster.ru +4 -0
  118. data/test/shell/run.sh +24 -0
  119. data/test/shell/t1.rb +19 -0
  120. data/test/shell/t1_conf.rb +3 -0
  121. data/test/shell/t2.rb +17 -0
  122. data/test/shell/t2_conf.rb +6 -0
  123. data/test/shell/t3.rb +25 -0
  124. data/test/shell/t3_conf.rb +5 -0
  125. data/test/slow.ru +4 -0
  126. data/test/ssl_config.rb +4 -0
  127. data/test/test_app_status.rb +93 -0
  128. data/test/test_binder.rb +31 -0
  129. data/test/test_cli.rb +209 -0
  130. data/test/test_config.rb +95 -0
  131. data/test/test_events.rb +161 -0
  132. data/test/test_helper.rb +50 -0
  133. data/test/test_http10.rb +27 -0
  134. data/test/test_http11.rb +186 -0
  135. data/test/test_integration.rb +247 -0
  136. data/test/test_iobuffer.rb +39 -0
  137. data/test/test_minissl.rb +29 -0
  138. data/test/test_null_io.rb +49 -0
  139. data/test/test_persistent.rb +245 -0
  140. data/test/test_puma_server.rb +626 -0
  141. data/test/test_puma_server_ssl.rb +222 -0
  142. data/test/test_rack_handler.rb +57 -0
  143. data/test/test_rack_server.rb +138 -0
  144. data/test/test_tcp_logger.rb +39 -0
  145. data/test/test_tcp_rack.rb +36 -0
  146. data/test/test_thread_pool.rb +250 -0
  147. data/test/test_unix_socket.rb +35 -0
  148. data/test/test_web_server.rb +88 -0
  149. data/tools/jungle/README.md +9 -0
  150. data/tools/jungle/init.d/README.md +59 -0
  151. data/tools/jungle/init.d/puma +421 -0
  152. data/tools/jungle/init.d/run-puma +18 -0
  153. data/tools/jungle/upstart/README.md +61 -0
  154. data/tools/jungle/upstart/puma-manager.conf +31 -0
  155. data/tools/jungle/upstart/puma.conf +69 -0
  156. data/tools/trickletest.rb +45 -0
  157. metadata +297 -0
@@ -0,0 +1,224 @@
1
+ #encoding: utf-8
2
+ module Puma
3
+ class UnsupportedOption < RuntimeError
4
+ end
5
+
6
+
7
+ # Every standard HTTP code mapped to the appropriate message. These are
8
+ # used so frequently that they are placed directly in Puma for easy
9
+ # access rather than Puma::Const itself.
10
+
11
+ # Every standard HTTP code mapped to the appropriate message.
12
+ # Generated with:
13
+ # curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \
14
+ # ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \
15
+ # puts "#{m[1]} => \x27#{m[2].strip}\x27,"'
16
+ HTTP_STATUS_CODES = {
17
+ 100 => 'Continue',
18
+ 101 => 'Switching Protocols',
19
+ 102 => 'Processing',
20
+ 200 => 'OK',
21
+ 201 => 'Created',
22
+ 202 => 'Accepted',
23
+ 203 => 'Non-Authoritative Information',
24
+ 204 => 'No Content',
25
+ 205 => 'Reset Content',
26
+ 206 => 'Partial Content',
27
+ 207 => 'Multi-Status',
28
+ 208 => 'Already Reported',
29
+ 226 => 'IM Used',
30
+ 300 => 'Multiple Choices',
31
+ 301 => 'Moved Permanently',
32
+ 302 => 'Found',
33
+ 303 => 'See Other',
34
+ 304 => 'Not Modified',
35
+ 305 => 'Use Proxy',
36
+ 307 => 'Temporary Redirect',
37
+ 308 => 'Permanent Redirect',
38
+ 400 => 'Bad Request',
39
+ 401 => 'Unauthorized',
40
+ 402 => 'Payment Required',
41
+ 403 => 'Forbidden',
42
+ 404 => 'Not Found',
43
+ 405 => 'Method Not Allowed',
44
+ 406 => 'Not Acceptable',
45
+ 407 => 'Proxy Authentication Required',
46
+ 408 => 'Request Timeout',
47
+ 409 => 'Conflict',
48
+ 410 => 'Gone',
49
+ 411 => 'Length Required',
50
+ 412 => 'Precondition Failed',
51
+ 413 => 'Payload Too Large',
52
+ 414 => 'URI Too Long',
53
+ 415 => 'Unsupported Media Type',
54
+ 416 => 'Range Not Satisfiable',
55
+ 417 => 'Expectation Failed',
56
+ 422 => 'Unprocessable Entity',
57
+ 423 => 'Locked',
58
+ 424 => 'Failed Dependency',
59
+ 426 => 'Upgrade Required',
60
+ 428 => 'Precondition Required',
61
+ 429 => 'Too Many Requests',
62
+ 431 => 'Request Header Fields Too Large',
63
+ 500 => 'Internal Server Error',
64
+ 501 => 'Not Implemented',
65
+ 502 => 'Bad Gateway',
66
+ 503 => 'Service Unavailable',
67
+ 504 => 'Gateway Timeout',
68
+ 505 => 'HTTP Version Not Supported',
69
+ 506 => 'Variant Also Negotiates',
70
+ 507 => 'Insufficient Storage',
71
+ 508 => 'Loop Detected',
72
+ 510 => 'Not Extended',
73
+ 511 => 'Network Authentication Required'
74
+ }
75
+
76
+ # For some HTTP status codes the client only expects headers.
77
+ #
78
+
79
+ STATUS_WITH_NO_ENTITY_BODY = {
80
+ 204 => true,
81
+ 205 => true,
82
+ 304 => true
83
+ }
84
+
85
+ # Frequently used constants when constructing requests or responses. Many times
86
+ # the constant just refers to a string with the same contents. Using these constants
87
+ # gave about a 3% to 10% performance improvement over using the strings directly.
88
+ #
89
+ # The constants are frozen because Hash#[]= when called with a String key dups
90
+ # the String UNLESS the String is frozen. This saves us therefore 2 object
91
+ # allocations when creating the env hash later.
92
+ #
93
+ # While Puma does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
94
+ # REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
95
+ # too taxing on performance.
96
+ module Const
97
+
98
+ PUMA_VERSION = VERSION = "3.7.1".freeze
99
+ CODE_NAME = "Snowy Sagebrush".freeze
100
+ PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
101
+
102
+ FAST_TRACK_KA_TIMEOUT = 0.2
103
+
104
+ # The default number of seconds for another request within a persistent
105
+ # session.
106
+ PERSISTENT_TIMEOUT = 20
107
+
108
+ # The default number of seconds to wait until we get the first data
109
+ # for the request
110
+ FIRST_DATA_TIMEOUT = 30
111
+
112
+ # How long to wait when getting some write blocking on the socket when
113
+ # sending data back
114
+ WRITE_TIMEOUT = 10
115
+
116
+ # The original URI requested by the client.
117
+ REQUEST_URI= 'REQUEST_URI'.freeze
118
+ REQUEST_PATH = 'REQUEST_PATH'.freeze
119
+ QUERY_STRING = 'QUERY_STRING'.freeze
120
+
121
+ PATH_INFO = 'PATH_INFO'.freeze
122
+
123
+ PUMA_TMP_BASE = "puma".freeze
124
+
125
+ # Indicate that we couldn't parse the request
126
+ ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
127
+
128
+ # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
129
+ ERROR_404_RESPONSE = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze
130
+
131
+ # The standard empty 408 response for requests that timed out.
132
+ ERROR_408_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n".freeze
133
+
134
+ CONTENT_LENGTH = "CONTENT_LENGTH".freeze
135
+
136
+ # Indicate that there was an internal error, obviously.
137
+ ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
138
+
139
+ # A common header for indicating the server is too busy. Not used yet.
140
+ ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
141
+
142
+ # The basic max request size we'll try to read.
143
+ CHUNK_SIZE = 16 * 1024
144
+
145
+ # This is the maximum header that is allowed before a client is booted. The parser detects
146
+ # this, but we'd also like to do this as well.
147
+ MAX_HEADER = 1024 * (80 + 32)
148
+
149
+ # Maximum request body size before it is moved out of memory and into a tempfile for reading.
150
+ MAX_BODY = MAX_HEADER
151
+
152
+ REQUEST_METHOD = "REQUEST_METHOD".freeze
153
+ HEAD = "HEAD".freeze
154
+ # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
155
+ LINE_END = "\r\n".freeze
156
+ REMOTE_ADDR = "REMOTE_ADDR".freeze
157
+ HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
158
+
159
+ SERVER_NAME = "SERVER_NAME".freeze
160
+ SERVER_PORT = "SERVER_PORT".freeze
161
+ HTTP_HOST = "HTTP_HOST".freeze
162
+ PORT_80 = "80".freeze
163
+ PORT_443 = "443".freeze
164
+ LOCALHOST = "localhost".freeze
165
+ LOCALHOST_IP = "127.0.0.1".freeze
166
+ LOCALHOST_ADDR = "127.0.0.1:0".freeze
167
+
168
+ SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
169
+ HTTP_11 = "HTTP/1.1".freeze
170
+
171
+ SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
172
+ GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
173
+ CGI_VER = "CGI/1.2".freeze
174
+
175
+ STOP_COMMAND = "?".freeze
176
+ HALT_COMMAND = "!".freeze
177
+ RESTART_COMMAND = "R".freeze
178
+
179
+ RACK_INPUT = "rack.input".freeze
180
+ RACK_URL_SCHEME = "rack.url_scheme".freeze
181
+ RACK_AFTER_REPLY = "rack.after_reply".freeze
182
+ PUMA_SOCKET = "puma.socket".freeze
183
+ PUMA_CONFIG = "puma.config".freeze
184
+ PUMA_PEERCERT = "puma.peercert".freeze
185
+
186
+ HTTP = "http".freeze
187
+ HTTPS = "https".freeze
188
+
189
+ HTTPS_KEY = "HTTPS".freeze
190
+
191
+ HTTP_VERSION = "HTTP_VERSION".freeze
192
+ HTTP_CONNECTION = "HTTP_CONNECTION".freeze
193
+ HTTP_EXPECT = "HTTP_EXPECT".freeze
194
+ CONTINUE = "100-continue".freeze
195
+
196
+ HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n".freeze
197
+ HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
198
+ HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
199
+
200
+ CLOSE = "close".freeze
201
+ KEEP_ALIVE = "keep-alive".freeze
202
+
203
+ CONTENT_LENGTH2 = "content-length".freeze
204
+ CONTENT_LENGTH_S = "Content-Length: ".freeze
205
+ TRANSFER_ENCODING = "transfer-encoding".freeze
206
+ TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
207
+
208
+ CONNECTION_CLOSE = "Connection: close\r\n".freeze
209
+ CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
210
+
211
+ TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
212
+ CLOSE_CHUNKED = "0\r\n\r\n".freeze
213
+
214
+ CHUNKED = "chunked".freeze
215
+
216
+ COLON = ": ".freeze
217
+
218
+ NEWLINE = "\n".freeze
219
+
220
+ HIJACK_P = "rack.hijack?".freeze
221
+ HIJACK = "rack.hijack".freeze
222
+ HIJACK_IO = "rack.hijack_io".freeze
223
+ end
224
+ end
@@ -0,0 +1,259 @@
1
+ require 'optparse'
2
+ require 'puma/state_file'
3
+ require 'puma/const'
4
+ require 'puma/detect'
5
+ require 'puma/configuration'
6
+ require 'uri'
7
+ require 'socket'
8
+
9
+ module Puma
10
+ class ControlCLI
11
+
12
+ COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
13
+
14
+ def initialize(argv, stdout=STDOUT, stderr=STDERR)
15
+ @state = nil
16
+ @quiet = false
17
+ @pidfile = nil
18
+ @pid = nil
19
+ @control_url = nil
20
+ @control_auth_token = nil
21
+ @config_file = nil
22
+ @command = nil
23
+
24
+ @argv = argv.dup
25
+ @stdout = stdout
26
+ @stderr = stderr
27
+ @cli_options = {}
28
+
29
+ opts = OptionParser.new do |o|
30
+ o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{COMMANDS.join("|")})"
31
+
32
+ o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
33
+ @state = arg
34
+ end
35
+
36
+ o.on "-Q", "--quiet", "Not display messages" do |arg|
37
+ @quiet = true
38
+ end
39
+
40
+ o.on "-P", "--pidfile PATH", "Pid file" do |arg|
41
+ @pidfile = arg
42
+ end
43
+
44
+ o.on "-p", "--pid PID", "Pid" do |arg|
45
+ @pid = arg.to_i
46
+ end
47
+
48
+ o.on "-C", "--control-url URL", "The bind url to use for the control server" do |arg|
49
+ @control_url = arg
50
+ end
51
+
52
+ o.on "-T", "--control-token TOKEN", "The token to use as authentication for the control server" do |arg|
53
+ @control_auth_token = arg
54
+ end
55
+
56
+ o.on "-F", "--config-file PATH", "Puma config script" do |arg|
57
+ @config_file = arg
58
+ end
59
+
60
+ o.on_tail("-H", "--help", "Show this message") do
61
+ @stdout.puts o
62
+ exit
63
+ end
64
+
65
+ o.on_tail("-V", "--version", "Show version") do
66
+ puts Const::PUMA_VERSION
67
+ exit
68
+ end
69
+ end
70
+
71
+ opts.order!(argv) { |a| opts.terminate a }
72
+
73
+ @command = argv.shift
74
+
75
+ unless @config_file == '-'
76
+ if @config_file.nil? and File.exist?('config/puma.rb')
77
+ @config_file = 'config/puma.rb'
78
+ end
79
+
80
+ if @config_file
81
+ config = Puma::Configuration.from_file @config_file
82
+ @state ||= config.options[:state]
83
+ @control_url ||= config.options[:control_url]
84
+ @control_auth_token ||= config.options[:control_auth_token]
85
+ @pidfile ||= config.options[:pidfile]
86
+ end
87
+ end
88
+
89
+ # check present of command
90
+ unless @command
91
+ raise "Available commands: #{COMMANDS.join(", ")}"
92
+ end
93
+
94
+ unless COMMANDS.include? @command
95
+ raise "Invalid command: #{@command}"
96
+ end
97
+
98
+ rescue => e
99
+ @stdout.puts e.message
100
+ exit 1
101
+ end
102
+
103
+ def message(msg)
104
+ @stdout.puts msg unless @quiet
105
+ end
106
+
107
+ def prepare_configuration
108
+ if @state
109
+ unless File.exist? @state
110
+ raise "State file not found: #{@state}"
111
+ end
112
+
113
+ sf = Puma::StateFile.new
114
+ sf.load @state
115
+
116
+ @control_url = sf.control_url
117
+ @control_auth_token = sf.control_auth_token
118
+ @pid = sf.pid
119
+ elsif @pidfile
120
+ # get pid from pid_file
121
+ @pid = File.open(@pidfile).gets.to_i
122
+ end
123
+ end
124
+
125
+ def send_request
126
+ uri = URI.parse @control_url
127
+
128
+ # create server object by scheme
129
+ @server = case uri.scheme
130
+ when "tcp"
131
+ TCPSocket.new uri.host, uri.port
132
+ when "unix"
133
+ UNIXSocket.new "#{uri.host}#{uri.path}"
134
+ else
135
+ raise "Invalid scheme: #{uri.scheme}"
136
+ end
137
+
138
+ if @command == "status"
139
+ message "Puma is started"
140
+ else
141
+ url = "/#{@command}"
142
+
143
+ if @control_auth_token
144
+ url = url + "?token=#{@control_auth_token}"
145
+ end
146
+
147
+ @server << "GET #{url} HTTP/1.0\r\n\r\n"
148
+
149
+ unless data = @server.read
150
+ raise "Server closed connection before responding"
151
+ end
152
+
153
+ response = data.split("\r\n")
154
+
155
+ if response.empty?
156
+ raise "Server sent empty response"
157
+ end
158
+
159
+ (@http,@code,@message) = response.first.split(" ",3)
160
+
161
+ if @code == "403"
162
+ raise "Unauthorized access to server (wrong auth token)"
163
+ elsif @code == "404"
164
+ raise "Command error: #{response.last}"
165
+ elsif @code != "200"
166
+ raise "Bad response from server: #{@code}"
167
+ end
168
+
169
+ message "Command #{@command} sent success"
170
+ message response.last if @command == "stats"
171
+ end
172
+
173
+ @server.close
174
+ end
175
+
176
+ def send_signal
177
+ unless @pid
178
+ raise "Neither pid nor control url available"
179
+ end
180
+
181
+ begin
182
+
183
+ case @command
184
+ when "restart"
185
+ Process.kill "SIGUSR2", @pid
186
+
187
+ when "halt"
188
+ Process.kill "QUIT", @pid
189
+
190
+ when "stop"
191
+ Process.kill "SIGTERM", @pid
192
+
193
+ when "stats"
194
+ puts "Stats not available via pid only"
195
+ return
196
+
197
+ when "reload-worker-directory"
198
+ puts "reload-worker-directory not available via pid only"
199
+ return
200
+
201
+ when "phased-restart"
202
+ Process.kill "SIGUSR1", @pid
203
+
204
+ else
205
+ message "Puma is started"
206
+ return
207
+ end
208
+
209
+ rescue SystemCallError
210
+ if @command == "restart"
211
+ start
212
+ else
213
+ raise "No pid '#{@pid}' found"
214
+ end
215
+ end
216
+
217
+ message "Command #{@command} sent success"
218
+ end
219
+
220
+ def run
221
+ start if @command == "start"
222
+
223
+ prepare_configuration
224
+
225
+ if Puma.windows?
226
+ send_request
227
+ else
228
+ @control_url ? send_request : send_signal
229
+ end
230
+
231
+ rescue => e
232
+ message e.message
233
+ exit 1
234
+ end
235
+
236
+ private
237
+ def start
238
+ require 'puma/cli'
239
+
240
+ run_args = []
241
+
242
+ run_args += ["-S", @state] if @state
243
+ run_args += ["-q"] if @quiet
244
+ run_args += ["--pidfile", @pidfile] if @pidfile
245
+ run_args += ["--control", @control_url] if @control_url
246
+ run_args += ["--control-token", @control_auth_token] if @control_auth_token
247
+ run_args += ["-C", @config_file] if @config_file
248
+
249
+ events = Puma::Events.new @stdout, @stderr
250
+
251
+ # replace $0 because puma use it to generate restart command
252
+ puma_cmd = $0.gsub(/pumactl$/, 'puma')
253
+ $0 = puma_cmd if File.exist?(puma_cmd)
254
+
255
+ cli = Puma::CLI.new run_args, events
256
+ cli.run
257
+ end
258
+ end
259
+ end