unicorn-simon 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 296319ebd9dc03db03c92e724df519984fafb751
4
- data.tar.gz: eceba679f90bf6d5c777a067d6fad24468ba8cb1
3
+ metadata.gz: 266572579d245f72975fd917d11fce58d24993ba
4
+ data.tar.gz: 027bb7a4b437f3634762ca7dfabed7dbc8b1d578
5
5
  SHA512:
6
- metadata.gz: 2bc1d883375fc4071a2d8c41b5c8388e9de5501e241e5bc83a652a9283030f997e366acde96f5fbc333ab89c19618996a8872a1c7f7890a96d0898169e8b75e5
7
- data.tar.gz: cfdd494e863019165dcb8d88359eb2ed545c6f494426447b2cffea72f8ec4c8a0e65f09b3bae0133ba9030c8de2bcd9eb3a7966b553e15d172da10643a087937
6
+ metadata.gz: 0c1d3a83abac0739e058425450ddeab6a920309a7cb2fc0eeab3be75df5b52e616a99db6619842a04aceaaf3cda9d2ca67e89145db8c89429e4c9d51686dfe14
7
+ data.tar.gz: ca8d4f6c4bbb2fcb0c0ef7fac7138ccfd50db3bbfb39bcd8c68d8ebb4fa5864704d4f018328ec465738c9c92d268e2cf61bc25a8be1ba0820e5de1528ff9a92a
@@ -29,8 +29,8 @@ class Unicorn::HttpParser
29
29
  # Drop these frozen strings when Ruby 2.2 becomes more prevalent,
30
30
  # 2.2+ optimizes hash assignments when used with literal string keys
31
31
  HTTP_RESPONSE_START = [ 'HTTP', '/1.1 ']
32
+ EMPTY_ARRAY = [].freeze
32
33
  @@input_class = Unicorn::TeeInput
33
- @@raindrops_tcp_info_defined = defined?(Raindrops::TCP_Info)
34
34
  @@check_client_connection = false
35
35
 
36
36
  def self.input_class
@@ -64,7 +64,7 @@ def self.check_client_connection=(bool)
64
64
  # returns an environment hash suitable for Rack if successful
65
65
  # This does minimal exception trapping and it is up to the caller
66
66
  # to handle any socket errors (e.g. user aborted upload).
67
- def read(socket)
67
+ def read(socket, listener)
68
68
  clear
69
69
  e = env
70
70
 
@@ -85,7 +85,7 @@ def read(socket)
85
85
  false until add_parse(socket.kgio_read!(16384))
86
86
  end
87
87
 
88
- check_client_connection(socket) if @@check_client_connection
88
+ check_client_connection(socket, listener) if @@check_client_connection
89
89
 
90
90
  e['rack.input'] = 0 == content_length ?
91
91
  NULL_IO : @@input_class.new(socket, self)
@@ -107,26 +107,37 @@ def hijacked?
107
107
  env.include?('rack.hijack_io'.freeze)
108
108
  end
109
109
 
110
- private
110
+ if defined?(Raindrops::TCP_Info)
111
+ def check_client_connection(socket, listener) # :nodoc:
112
+ if Kgio::TCPServer === listener
113
+ @@tcp_info ||= Raindrops::TCP_Info.new(socket)
114
+ @@tcp_info.get!(socket)
115
+ raise Errno::EPIPE, "client closed connection".freeze, EMPTY_ARRAY if closed_state?(tcp_info.state)
116
+ else
117
+ write_http_header(socket)
118
+ end
119
+ end
111
120
 
112
- def check_client_connection(socket)
113
- if @@raindrops_tcp_info_defined
114
- tcp_info = Raindrops::TCP_Info.new(socket)
115
- raise Errno::EPIPE, "client closed connection state=#{tcp_info.state} socket_class=#{socket.class}", [] if closed_state?(tcp_info.state)
116
- elsif headers?
117
- self.response_start_sent = true
118
- HTTP_RESPONSE_START.each { |c| socket.write(c) }
121
+ def closed_state?(state) # :nodoc:
122
+ case state
123
+ when 1 # ESTABLISHED
124
+ false
125
+ when 8, 6, 7, 9, 11 # CLOSE_WAIT, TIME_WAIT, CLOSE, LAST_ACK, CLOSING
126
+ true
127
+ else
128
+ false
129
+ end
130
+ end
131
+ else
132
+ def check_client_connection(socket, listener) # :nodoc:
133
+ write_http_header(socket)
119
134
  end
120
135
  end
121
136
 
122
- def closed_state?(state)
123
- case state
124
- when 1 # ESTABLISHED
125
- false
126
- when 6, 7, 8, 9, 11 # TIME_WAIT, CLOSE, CLOSE_WAIT, LAST_ACK, CLOSING
127
- true
128
- else
129
- false
137
+ def write_http_header(socket) # :nodoc:
138
+ if headers?
139
+ self.response_start_sent = true
140
+ HTTP_RESPONSE_START.each { |c| socket.write(c) }
130
141
  end
131
142
  end
132
143
  end
@@ -559,8 +559,8 @@ def e100_response_write(client, env)
559
559
 
560
560
  # once a client is accepted, it is processed in its entirety here
561
561
  # in 3 easy steps: read request, call app, write app response
562
- def process_client(client)
563
- status, headers, body = @app.call(env = @request.read(client))
562
+ def process_client(client, listener)
563
+ status, headers, body = @app.call(env = @request.read(client, listener))
564
564
 
565
565
  begin
566
566
  return if @request.hijacked?
@@ -656,7 +656,7 @@ def worker_loop(worker)
656
656
  # Unicorn::Worker#kgio_tryaccept is not like accept(2) at all,
657
657
  # but that will return false
658
658
  if client = sock.kgio_tryaccept
659
- process_client(client)
659
+ process_client(client, sock)
660
660
  nr += 1
661
661
  worker.tick = time_now.to_i
662
662
  end
@@ -30,7 +30,7 @@ def setup
30
30
  def test_options
31
31
  client = MockRequest.new("OPTIONS * HTTP/1.1\r\n" \
32
32
  "Host: foo\r\n\r\n")
33
- env = @request.read(client)
33
+ env = @request.read(client, nil)
34
34
  assert_equal '', env['REQUEST_PATH']
35
35
  assert_equal '', env['PATH_INFO']
36
36
  assert_equal '*', env['REQUEST_URI']
@@ -40,7 +40,7 @@ def test_options
40
40
  def test_absolute_uri_with_query
41
41
  client = MockRequest.new("GET http://e:3/x?y=z HTTP/1.1\r\n" \
42
42
  "Host: foo\r\n\r\n")
43
- env = @request.read(client)
43
+ env = @request.read(client, nil)
44
44
  assert_equal '/x', env['REQUEST_PATH']
45
45
  assert_equal '/x', env['PATH_INFO']
46
46
  assert_equal 'y=z', env['QUERY_STRING']
@@ -50,7 +50,7 @@ def test_absolute_uri_with_query
50
50
  def test_absolute_uri_with_fragment
51
51
  client = MockRequest.new("GET http://e:3/x#frag HTTP/1.1\r\n" \
52
52
  "Host: foo\r\n\r\n")
53
- env = @request.read(client)
53
+ env = @request.read(client, nil)
54
54
  assert_equal '/x', env['REQUEST_PATH']
55
55
  assert_equal '/x', env['PATH_INFO']
56
56
  assert_equal '', env['QUERY_STRING']
@@ -61,7 +61,7 @@ def test_absolute_uri_with_fragment
61
61
  def test_absolute_uri_with_query_and_fragment
62
62
  client = MockRequest.new("GET http://e:3/x?a=b#frag HTTP/1.1\r\n" \
63
63
  "Host: foo\r\n\r\n")
64
- env = @request.read(client)
64
+ env = @request.read(client, nil)
65
65
  assert_equal '/x', env['REQUEST_PATH']
66
66
  assert_equal '/x', env['PATH_INFO']
67
67
  assert_equal 'a=b', env['QUERY_STRING']
@@ -73,7 +73,7 @@ def test_absolute_uri_unsupported_schemes
73
73
  %w(ssh+http://e/ ftp://e/x http+ssh://e/x).each do |abs_uri|
74
74
  client = MockRequest.new("GET #{abs_uri} HTTP/1.1\r\n" \
75
75
  "Host: foo\r\n\r\n")
76
- assert_raises(HttpParserError) { @request.read(client) }
76
+ assert_raises(HttpParserError) { @request.read(client, nil) }
77
77
  end
78
78
  end
79
79
 
@@ -81,7 +81,7 @@ def test_x_forwarded_proto_https
81
81
  client = MockRequest.new("GET / HTTP/1.1\r\n" \
82
82
  "X-Forwarded-Proto: https\r\n" \
83
83
  "Host: foo\r\n\r\n")
84
- env = @request.read(client)
84
+ env = @request.read(client, nil)
85
85
  assert_equal "https", env['rack.url_scheme']
86
86
  res = @lint.call(env)
87
87
  end
@@ -90,7 +90,7 @@ def test_x_forwarded_proto_http
90
90
  client = MockRequest.new("GET / HTTP/1.1\r\n" \
91
91
  "X-Forwarded-Proto: http\r\n" \
92
92
  "Host: foo\r\n\r\n")
93
- env = @request.read(client)
93
+ env = @request.read(client, nil)
94
94
  assert_equal "http", env['rack.url_scheme']
95
95
  res = @lint.call(env)
96
96
  end
@@ -99,14 +99,14 @@ def test_x_forwarded_proto_invalid
99
99
  client = MockRequest.new("GET / HTTP/1.1\r\n" \
100
100
  "X-Forwarded-Proto: ftp\r\n" \
101
101
  "Host: foo\r\n\r\n")
102
- env = @request.read(client)
102
+ env = @request.read(client, nil)
103
103
  assert_equal "http", env['rack.url_scheme']
104
104
  res = @lint.call(env)
105
105
  end
106
106
 
107
107
  def test_rack_lint_get
108
108
  client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
109
- env = @request.read(client)
109
+ env = @request.read(client, nil)
110
110
  assert_equal "http", env['rack.url_scheme']
111
111
  assert_equal '127.0.0.1', env['REMOTE_ADDR']
112
112
  res = @lint.call(env)
@@ -114,7 +114,7 @@ def test_rack_lint_get
114
114
 
115
115
  def test_no_content_stringio
116
116
  client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
117
- env = @request.read(client)
117
+ env = @request.read(client, nil)
118
118
  assert_equal StringIO, env['rack.input'].class
119
119
  end
120
120
 
@@ -122,7 +122,7 @@ def test_zero_content_stringio
122
122
  client = MockRequest.new("PUT / HTTP/1.1\r\n" \
123
123
  "Content-Length: 0\r\n" \
124
124
  "Host: foo\r\n\r\n")
125
- env = @request.read(client)
125
+ env = @request.read(client, nil)
126
126
  assert_equal StringIO, env['rack.input'].class
127
127
  end
128
128
 
@@ -130,7 +130,7 @@ def test_real_content_not_stringio
130
130
  client = MockRequest.new("PUT / HTTP/1.1\r\n" \
131
131
  "Content-Length: 1\r\n" \
132
132
  "Host: foo\r\n\r\n")
133
- env = @request.read(client)
133
+ env = @request.read(client, nil)
134
134
  assert_equal Unicorn::TeeInput, env['rack.input'].class
135
135
  end
136
136
 
@@ -141,7 +141,7 @@ def test_rack_lint_put
141
141
  "Content-Length: 5\r\n" \
142
142
  "\r\n" \
143
143
  "abcde")
144
- env = @request.read(client)
144
+ env = @request.read(client, nil)
145
145
  assert ! env.include?(:http_body)
146
146
  res = @lint.call(env)
147
147
  end
@@ -167,7 +167,7 @@ def client.kgio_read!(*args)
167
167
  "\r\n")
168
168
  count.times { assert_equal bs, client.syswrite(buf) }
169
169
  assert_equal 0, client.sysseek(0)
170
- env = @request.read(client)
170
+ env = @request.read(client, nil)
171
171
  assert ! env.include?(:http_body)
172
172
  assert_equal length, env['rack.input'].size
173
173
  count.times {
@@ -103,59 +103,6 @@ def test_simple_server
103
103
  assert_equal 'hello!\n', results[0], "Handler didn't really run"
104
104
  end
105
105
 
106
- def test_client_shutdown_writes
107
- bs = 15609315 * rand
108
- sock = TCPSocket.new('127.0.0.1', @port)
109
- sock.syswrite("PUT /hello HTTP/1.1\r\n")
110
- sock.syswrite("Host: example.com\r\n")
111
- sock.syswrite("Transfer-Encoding: chunked\r\n")
112
- sock.syswrite("Trailer: X-Foo\r\n")
113
- sock.syswrite("\r\n")
114
- sock.syswrite("%x\r\n" % [ bs ])
115
- sock.syswrite("F" * bs)
116
- sock.syswrite("\r\n0\r\nX-")
117
- "Foo: bar\r\n\r\n".each_byte do |x|
118
- sock.syswrite x.chr
119
- sleep 0.05
120
- end
121
- # we wrote the entire request before shutting down, server should
122
- # continue to process our request and never hit EOFError on our sock
123
- sock.shutdown(Socket::SHUT_WR)
124
- buf = sock.read
125
- assert_equal 'hello!\n', buf.split(/\r\n\r\n/).last
126
- next_client = Net::HTTP.get(URI.parse("http://127.0.0.1:#@port/"))
127
- assert_equal 'hello!\n', next_client
128
- lines = File.readlines("test_stderr.#$$.log")
129
- assert lines.grep(/^Unicorn::ClientShutdown: /).empty?
130
- assert_nil sock.close
131
- end
132
-
133
- def test_client_shutdown_write_truncates
134
- bs = 15609315 * rand
135
- sock = TCPSocket.new('127.0.0.1', @port)
136
- sock.syswrite("PUT /hello HTTP/1.1\r\n")
137
- sock.syswrite("Host: example.com\r\n")
138
- sock.syswrite("Transfer-Encoding: chunked\r\n")
139
- sock.syswrite("Trailer: X-Foo\r\n")
140
- sock.syswrite("\r\n")
141
- sock.syswrite("%x\r\n" % [ bs ])
142
- sock.syswrite("F" * (bs / 2.0))
143
-
144
- # shutdown prematurely, this will force the server to abort
145
- # processing on us even during app dispatch
146
- sock.shutdown(Socket::SHUT_WR)
147
- IO.select([sock], nil, nil, 60) or raise "Timed out"
148
- buf = sock.read
149
- assert_equal "", buf
150
- next_client = Net::HTTP.get(URI.parse("http://127.0.0.1:#@port/"))
151
- assert_equal 'hello!\n', next_client
152
- lines = File.readlines("test_stderr.#$$.log")
153
- lines = lines.grep(/^Unicorn::ClientShutdown: bytes_read=\d+/)
154
- assert_equal 1, lines.size
155
- assert_match %r{\AUnicorn::ClientShutdown: bytes_read=\d+ true$}, lines[0]
156
- assert_nil sock.close
157
- end
158
-
159
106
  def test_client_malformed_body
160
107
  bs = 15653984
161
108
  sock = TCPSocket.new('127.0.0.1', @port)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn-simon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - unicorn hackers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-26 00:00:00.000000000 Z
11
+ date: 2017-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack