puma 2.11.3-java → 2.12.0-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Binary file
@@ -0,0 +1,56 @@
1
+ # :stopdoc:
2
+
3
+ # Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
4
+ #
5
+ # https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
6
+ #
7
+ #
8
+
9
+ module URI
10
+ TBLENCWWWCOMP_ = {} # :nodoc:
11
+ 256.times do |i|
12
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
13
+ end
14
+ TBLENCWWWCOMP_[' '] = '+'
15
+ TBLENCWWWCOMP_.freeze
16
+ TBLDECWWWCOMP_ = {} # :nodoc:
17
+ 256.times do |i|
18
+ h, l = i>>4, i&15
19
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
20
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
21
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
22
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
23
+ end
24
+ TBLDECWWWCOMP_['+'] = ' '
25
+ TBLDECWWWCOMP_.freeze
26
+
27
+ # Encode given +s+ to URL-encoded form data.
28
+ #
29
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
30
+ # (ASCII space) to + and converts others to %XX.
31
+ #
32
+ # This is an implementation of
33
+ # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
34
+ #
35
+ # See URI.decode_www_form_component, URI.encode_www_form
36
+ def self.encode_www_form_component(s)
37
+ str = s.to_s
38
+ if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
39
+ str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
40
+ '%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
41
+ end.tr(' ', '+')
42
+ else
43
+ str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
44
+ end
45
+ end
46
+
47
+ # Decode given +str+ of URL-encoded form data.
48
+ #
49
+ # This decodes + to SP.
50
+ #
51
+ # See URI.encode_www_form_component, URI.decode_www_form
52
+ def self.decode_www_form_component(str, enc=nil)
53
+ raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str
54
+ str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]}
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ # :stopdoc:
2
+
3
+ # Stolen from ruby core's uri/common.rb @32618ba to fix DoS issues in 1.9.2
4
+ #
5
+ # https://github.com/ruby/ruby/blob/32618ba7438a2247042bba9b5d85b5d49070f5e5/lib/uri/common.rb
6
+ #
7
+ # Issue:
8
+ # http://redmine.ruby-lang.org/issues/5149
9
+ #
10
+ # Relevant Fixes:
11
+ # https://github.com/ruby/ruby/commit/b5f91deee04aa6ccbe07c23c8222b937c22a799b
12
+ # https://github.com/ruby/ruby/commit/93177c1e5c3906abf14472ae0b905d8b5c72ce1b
13
+ #
14
+ # This should probably be removed once there is a Ruby 1.9.2 patch level that
15
+ # includes this fix.
16
+
17
+ require 'uri/common'
18
+
19
+ module URI
20
+ TBLDECWWWCOMP_ = {} unless const_defined?(:TBLDECWWWCOMP_) #:nodoc:
21
+ if TBLDECWWWCOMP_.empty?
22
+ 256.times do |i|
23
+ h, l = i>>4, i&15
24
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
25
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
26
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
27
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
28
+ end
29
+ TBLDECWWWCOMP_['+'] = ' '
30
+ TBLDECWWWCOMP_.freeze
31
+ end
32
+
33
+ def self.decode_www_form(str, enc=Encoding::UTF_8)
34
+ return [] if str.empty?
35
+ unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/o =~ str
36
+ raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
37
+ end
38
+ ary = []
39
+ $&.scan(/([^=;&]+)=([^;&]*)/) do
40
+ ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
41
+ end
42
+ ary
43
+ end
44
+
45
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
46
+ raise ArgumentError, "invalid %-encoding (#{str})" unless /\A[^%]*(?:%\h\h[^%]*)*\z/ =~ str
47
+ str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
48
+ end
49
+
50
+ remove_const :WFKV_ if const_defined?(:WFKV_)
51
+ WFKV_ = '(?:[^%#=;&]*(?:%\h\h[^%#=;&]*)*)' # :nodoc:
52
+ end
@@ -0,0 +1,29 @@
1
+ # :stopdoc:
2
+
3
+ require 'uri/common'
4
+
5
+ # Issue:
6
+ # http://bugs.ruby-lang.org/issues/5925
7
+ #
8
+ # Relevant commit:
9
+ # https://github.com/ruby/ruby/commit/edb7cdf1eabaff78dfa5ffedfbc2e91b29fa9ca1
10
+
11
+ module URI
12
+ 256.times do |i|
13
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
14
+ end
15
+ TBLENCWWWCOMP_[' '] = '+'
16
+ TBLENCWWWCOMP_.freeze
17
+
18
+ 256.times do |i|
19
+ h, l = i>>4, i&15
20
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
21
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
22
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
23
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
24
+ end
25
+ TBLDECWWWCOMP_['+'] = ' '
26
+ TBLDECWWWCOMP_.freeze
27
+ end
28
+
29
+ # :startdoc:
@@ -0,0 +1,298 @@
1
+ module PumaRackCompat
2
+ BINDING = binding
3
+
4
+ def self.const_missing(cm)
5
+ if cm == :Rack
6
+ require 'rack'
7
+ Rack
8
+ else
9
+ raise NameError, "constant undefined: #{cm}"
10
+ end
11
+ end
12
+ end
13
+
14
+ module Puma::Rack
15
+ class Options
16
+ def parse!(args)
17
+ options = {}
18
+ opt_parser = OptionParser.new("", 24, ' ') do |opts|
19
+ opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]"
20
+
21
+ opts.separator ""
22
+ opts.separator "Ruby options:"
23
+
24
+ lineno = 1
25
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
26
+ eval line, TOPLEVEL_BINDING, "-e", lineno
27
+ lineno += 1
28
+ }
29
+
30
+ opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line|
31
+ options[:builder] = line
32
+ }
33
+
34
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
35
+ options[:debug] = true
36
+ }
37
+ opts.on("-w", "--warn", "turn warnings on for your script") {
38
+ options[:warn] = true
39
+ }
40
+ opts.on("-q", "--quiet", "turn off logging") {
41
+ options[:quiet] = true
42
+ }
43
+
44
+ opts.on("-I", "--include PATH",
45
+ "specify $LOAD_PATH (may be used more than once)") { |path|
46
+ (options[:include] ||= []).concat(path.split(":"))
47
+ }
48
+
49
+ opts.on("-r", "--require LIBRARY",
50
+ "require the library, before executing your script") { |library|
51
+ options[:require] = library
52
+ }
53
+
54
+ opts.separator ""
55
+ opts.separator "Rack options:"
56
+ opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick/mongrel)") { |s|
57
+ options[:server] = s
58
+ }
59
+
60
+ opts.on("-o", "--host HOST", "listen on HOST (default: localhost)") { |host|
61
+ options[:Host] = host
62
+ }
63
+
64
+ opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port|
65
+ options[:Port] = port
66
+ }
67
+
68
+ opts.on("-O", "--option NAME[=VALUE]", "pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} -s SERVER -h' to get a list of options for SERVER") { |name|
69
+ name, value = name.split('=', 2)
70
+ value = true if value.nil?
71
+ options[name.to_sym] = value
72
+ }
73
+
74
+ opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
75
+ options[:environment] = e
76
+ }
77
+
78
+ opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
79
+ options[:daemonize] = d ? true : false
80
+ }
81
+
82
+ opts.on("-P", "--pid FILE", "file to store PID") { |f|
83
+ options[:pid] = ::File.expand_path(f)
84
+ }
85
+
86
+ opts.separator ""
87
+ opts.separator "Common options:"
88
+
89
+ opts.on_tail("-h", "-?", "--help", "Show this message") do
90
+ puts opts
91
+ puts handler_opts(options)
92
+
93
+ exit
94
+ end
95
+
96
+ opts.on_tail("--version", "Show version") do
97
+ puts "Rack #{Rack.version} (Release: #{Rack.release})"
98
+ exit
99
+ end
100
+ end
101
+
102
+ begin
103
+ opt_parser.parse! args
104
+ rescue OptionParser::InvalidOption => e
105
+ warn e.message
106
+ abort opt_parser.to_s
107
+ end
108
+
109
+ options[:config] = args.last if args.last
110
+ options
111
+ end
112
+
113
+ def handler_opts(options)
114
+ begin
115
+ info = []
116
+ server = Rack::Handler.get(options[:server]) || Rack::Handler.default(options)
117
+ if server && server.respond_to?(:valid_options)
118
+ info << ""
119
+ info << "Server-specific options for #{server.name}:"
120
+
121
+ has_options = false
122
+ server.valid_options.each do |name, description|
123
+ next if name.to_s.match(/^(Host|Port)[^a-zA-Z]/) # ignore handler's host and port options, we do our own.
124
+ info << " -O %-21s %s" % [name, description]
125
+ has_options = true
126
+ end
127
+ return "" if !has_options
128
+ end
129
+ info.join("\n")
130
+ rescue NameError
131
+ return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options"
132
+ end
133
+ end
134
+ end
135
+
136
+ # Rack::Builder implements a small DSL to iteratively construct Rack
137
+ # applications.
138
+ #
139
+ # Example:
140
+ #
141
+ # require 'rack/lobster'
142
+ # app = Rack::Builder.new do
143
+ # use Rack::CommonLogger
144
+ # use Rack::ShowExceptions
145
+ # map "/lobster" do
146
+ # use Rack::Lint
147
+ # run Rack::Lobster.new
148
+ # end
149
+ # end
150
+ #
151
+ # run app
152
+ #
153
+ # Or
154
+ #
155
+ # app = Rack::Builder.app do
156
+ # use Rack::CommonLogger
157
+ # run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] }
158
+ # end
159
+ #
160
+ # run app
161
+ #
162
+ # +use+ adds middleware to the stack, +run+ dispatches to an application.
163
+ # You can use +map+ to construct a Rack::URLMap in a convenient way.
164
+
165
+ class Builder
166
+ def self.parse_file(config, opts = Options.new)
167
+ options = {}
168
+ if config =~ /\.ru$/
169
+ cfgfile = ::File.read(config)
170
+ if cfgfile[/^#\\(.*)/] && opts
171
+ options = opts.parse! $1.split(/\s+/)
172
+ end
173
+ cfgfile.sub!(/^__END__\n.*\Z/m, '')
174
+ app = new_from_string cfgfile, config
175
+ else
176
+ require config
177
+ app = Object.const_get(::File.basename(config, '.rb').capitalize)
178
+ end
179
+ return app, options
180
+ end
181
+
182
+ def self.new_from_string(builder_script, file="(rackup)")
183
+ eval "Puma::Rack::Builder.new {\n" + builder_script + "\n}.to_app",
184
+ PumaRackCompat::BINDING, file, 0
185
+ end
186
+
187
+ def initialize(default_app = nil,&block)
188
+ @use, @map, @run, @warmup = [], nil, default_app, nil
189
+ instance_eval(&block) if block_given?
190
+ end
191
+
192
+ def self.app(default_app = nil, &block)
193
+ self.new(default_app, &block).to_app
194
+ end
195
+
196
+ # Specifies middleware to use in a stack.
197
+ #
198
+ # class Middleware
199
+ # def initialize(app)
200
+ # @app = app
201
+ # end
202
+ #
203
+ # def call(env)
204
+ # env["rack.some_header"] = "setting an example"
205
+ # @app.call(env)
206
+ # end
207
+ # end
208
+ #
209
+ # use Middleware
210
+ # run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
211
+ #
212
+ # All requests through to this application will first be processed by the middleware class.
213
+ # The +call+ method in this example sets an additional environment key which then can be
214
+ # referenced in the application if required.
215
+ def use(middleware, *args, &block)
216
+ if @map
217
+ mapping, @map = @map, nil
218
+ @use << proc { |app| generate_map app, mapping }
219
+ end
220
+ @use << proc { |app| middleware.new(app, *args, &block) }
221
+ end
222
+
223
+ # Takes an argument that is an object that responds to #call and returns a Rack response.
224
+ # The simplest form of this is a lambda object:
225
+ #
226
+ # run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
227
+ #
228
+ # However this could also be a class:
229
+ #
230
+ # class Heartbeat
231
+ # def self.call(env)
232
+ # [200, { "Content-Type" => "text/plain" }, ["OK"]]
233
+ # end
234
+ # end
235
+ #
236
+ # run Heartbeat
237
+ def run(app)
238
+ @run = app
239
+ end
240
+
241
+ # Takes a lambda or block that is used to warm-up the application.
242
+ #
243
+ # warmup do |app|
244
+ # client = Rack::MockRequest.new(app)
245
+ # client.get('/')
246
+ # end
247
+ #
248
+ # use SomeMiddleware
249
+ # run MyApp
250
+ def warmup(prc=nil, &block)
251
+ @warmup = prc || block
252
+ end
253
+
254
+ # Creates a route within the application.
255
+ #
256
+ # Rack::Builder.app do
257
+ # map '/' do
258
+ # run Heartbeat
259
+ # end
260
+ # end
261
+ #
262
+ # The +use+ method can also be used here to specify middleware to run under a specific path:
263
+ #
264
+ # Rack::Builder.app do
265
+ # map '/' do
266
+ # use Middleware
267
+ # run Heartbeat
268
+ # end
269
+ # end
270
+ #
271
+ # This example includes a piece of middleware which will run before requests hit +Heartbeat+.
272
+ #
273
+ def map(path, &block)
274
+ @map ||= {}
275
+ @map[path] = block
276
+ end
277
+
278
+ def to_app
279
+ app = @map ? generate_map(@run, @map) : @run
280
+ fail "missing run or map statement" unless app
281
+ app = @use.reverse.inject(app) { |a,e| e[a] }
282
+ @warmup.call(app) if @warmup
283
+ app
284
+ end
285
+
286
+ def call(env)
287
+ to_app.call(env)
288
+ end
289
+
290
+ private
291
+
292
+ def generate_map(default_app, mapping)
293
+ mapped = default_app ? {'/' => default_app} : {}
294
+ mapping.each { |r,b| mapped[r] = self.class.new(default_app, &b).to_app }
295
+ URLMap.new(mapped)
296
+ end
297
+ end
298
+ end
@@ -74,6 +74,17 @@ module Puma
74
74
  sockets.delete c
75
75
  end
76
76
 
77
+ # SSL handshake failure
78
+ rescue MiniSSL::SSLError => e
79
+ ssl_socket = c.io
80
+ addr = ssl_socket.peeraddr.last
81
+ cert = ssl_socket.peercert
82
+
83
+ c.close
84
+ sockets.delete c
85
+
86
+ @events.ssl_error @server, addr, cert, e
87
+
77
88
  # The client doesn't know HTTP well
78
89
  rescue HttpParserError => e
79
90
  c.write_400