yahns 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/GIT-VERSION-GEN +1 -1
- data/INSTALL +1 -3
- data/README +1 -2
- data/Rakefile +2 -2
- data/extras/autoindex.rb +3 -1
- data/lib/yahns/config.rb +3 -2
- data/lib/yahns/http_context.rb +0 -1
- data/lib/yahns/http_response.rb +5 -6
- data/lib/yahns/openssl_client.rb +54 -0
- data/lib/yahns/openssl_server.rb +21 -0
- data/lib/yahns/rackup_handler.rb +2 -2
- data/lib/yahns/sendfile_compat.rb +5 -7
- data/lib/yahns/server.rb +9 -9
- data/lib/yahns/socket_helper.rb +13 -4
- data/lib/yahns/tmpio.rb +1 -1
- data/lib/yahns/wbuf_common.rb +7 -3
- data/test/server_helper.rb +3 -3
- data/test/test_serve_static.rb +61 -0
- data/test/test_ssl.rb +79 -0
- data/yahns.gemspec +1 -1
- metadata +6 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b72841cf8d034892a5616279ac723d75439b9a2c
|
4
|
+
data.tar.gz: 01710a8efb79f9eb9262775c4f3dcea178c302c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d80a9d094e857d97f7192c1aa79ad7235dae23a85bd2a0967c8a83cf26960f04dcfc89300182b8fb2235dde9b6cae7ca3717d2c89e830f6815c625c0c2d99d15
|
7
|
+
data.tar.gz: 11a80294b69429051ddcdc3121f12f4179251271de70bf344a73b39deaea190b91d3004a273f162e57fcc12306ae48bd7cda1c5c6758d306de88585f6f7d7131
|
data/GIT-VERSION-GEN
CHANGED
data/INSTALL
CHANGED
data/README
CHANGED
@@ -48,8 +48,7 @@ We have experimental support kqueue on FreeBSD (and possibly OpenBSD and
|
|
48
48
|
NetBSD). Non-Free systems/dependencies will never be supported.
|
49
49
|
|
50
50
|
Supported Ruby implementations:
|
51
|
-
* (Matz) Ruby
|
52
|
-
* Rubinius 2.0 or later (best-effort)
|
51
|
+
* (Matz) Ruby 2.0.0 and later (we develop (and host our website) on trunk)
|
53
52
|
|
54
53
|
Contact
|
55
54
|
-------
|
data/Rakefile
CHANGED
@@ -116,11 +116,11 @@ task "NEWS" do
|
|
116
116
|
time = nil
|
117
117
|
tags.each do |tag|
|
118
118
|
time ||= tag[:time_obj]
|
119
|
-
line = tag[:subject] + " / " + tag[:time].
|
119
|
+
line = tag[:subject] + " / " + tag[:time].sub(/T.*/, '')
|
120
120
|
fp.puts line
|
121
121
|
fp.puts("-" * line.length)
|
122
122
|
fp.puts
|
123
|
-
fp.puts tag[:body]
|
123
|
+
fp.puts tag[:body]
|
124
124
|
fp.puts
|
125
125
|
end
|
126
126
|
fp.write("Unreleased\n\n") unless fp.size > 0
|
data/extras/autoindex.rb
CHANGED
@@ -107,7 +107,9 @@ class Autoindex
|
|
107
107
|
|
108
108
|
if ngz_idx
|
109
109
|
ngz_idx.each do |name, entry|
|
110
|
-
|
110
|
+
# n.b: use use dup.sub! to ensure ngz_path is nil
|
111
|
+
# if .gz is not found
|
112
|
+
ngz_path = name.dup.sub!(/\.gz\z/, '')
|
111
113
|
ngz_idx.include?(ngz_path) or files << entry
|
112
114
|
end
|
113
115
|
end
|
data/lib/yahns/config.rb
CHANGED
@@ -202,6 +202,8 @@ class Yahns::Config # :nodoc:
|
|
202
202
|
raise ArgumentError, "#{var}: not boolean: #{key}=#{value.inspect}"
|
203
203
|
end
|
204
204
|
|
205
|
+
require_relative('openssl_server') if options[:ssl_ctx]
|
206
|
+
|
205
207
|
options[:yahns_app_ctx] = @block.ctx
|
206
208
|
@config_listeners.include?(address) and
|
207
209
|
raise ArgumentError, "listen #{address} already in use"
|
@@ -363,7 +365,6 @@ class Yahns::Config # :nodoc:
|
|
363
365
|
# config name, minimum value
|
364
366
|
client_body_buffer_size: 1,
|
365
367
|
client_header_buffer_size: 1,
|
366
|
-
client_max_header_size: 1,
|
367
368
|
}.each do |_v,minval|
|
368
369
|
eval(
|
369
370
|
%Q(def #{_v}(val);) <<
|
@@ -403,7 +404,7 @@ class Yahns::Config # :nodoc:
|
|
403
404
|
val.close_on_exec = val.sync = true
|
404
405
|
val.binmode
|
405
406
|
else
|
406
|
-
rt =
|
407
|
+
rt = [ :puts, :write, :flush ] # match Rack::Lint
|
407
408
|
rt.all? { |m| val.respond_to?(m) } or raise ArgumentError,
|
408
409
|
"`#{var}' destination must respond to all of: #{rt.inspect}"
|
409
410
|
end
|
data/lib/yahns/http_context.rb
CHANGED
@@ -9,7 +9,6 @@ module Yahns::HttpContext # :nodoc:
|
|
9
9
|
attr_accessor :client_body_buffer_size
|
10
10
|
attr_accessor :client_header_buffer_size
|
11
11
|
attr_accessor :client_max_body_size
|
12
|
-
attr_accessor :client_max_header_size
|
13
12
|
attr_accessor :input_buffering # :lazy, true, false
|
14
13
|
attr_accessor :output_buffering # true, false
|
15
14
|
attr_accessor :persistent_connections # true or false only
|
data/lib/yahns/http_response.rb
CHANGED
@@ -27,10 +27,7 @@ module Yahns::HttpResponse # :nodoc:
|
|
27
27
|
CONN_CLOSE = "Connection: close\r\n\r\n"
|
28
28
|
Z = ""
|
29
29
|
CCC_RESPONSE_START = [ 'HTTP', '/1.1 ' ]
|
30
|
-
RESPONSE_START = CCC_RESPONSE_START.join
|
31
|
-
R100_RAW = "HTTP/1.1 100 Continue\r\n\r\n"
|
32
|
-
R100_CCC = "100 Continue\r\n\r\nHTTP/1.1 "
|
33
|
-
HTTP_EXPECT = "HTTP_EXPECT"
|
30
|
+
RESPONSE_START = CCC_RESPONSE_START.join
|
34
31
|
REQUEST_METHOD = "REQUEST_METHOD"
|
35
32
|
HEAD = "HEAD"
|
36
33
|
|
@@ -258,8 +255,10 @@ module Yahns::HttpResponse # :nodoc:
|
|
258
255
|
# returns nil on success
|
259
256
|
# returns :close, :wait_writable, or :wait_readable
|
260
257
|
def http_100_response(env)
|
261
|
-
env.delete(HTTP_EXPECT) =~ /\A100-continue\z/i or return
|
262
|
-
buf = @response_start_sent ?
|
258
|
+
env.delete("HTTP_EXPECT") =~ /\A100-continue\z/i or return
|
259
|
+
buf = @response_start_sent ? "100 Continue\r\n\r\nHTTP/1.1 ".freeze
|
260
|
+
: "HTTP/1.1 100 Continue\r\n\r\n".freeze
|
261
|
+
|
263
262
|
case rv = kgio_trywrite(buf)
|
264
263
|
when String
|
265
264
|
buf = rv
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (C) 2014, all contributors <yahns-public@yhbt.net>
|
2
|
+
# License: GPLv3 or later (see COPYING for details)
|
3
|
+
|
4
|
+
require_relative 'sendfile_compat'
|
5
|
+
|
6
|
+
# this is to be included into a Kgio::Socket-derived class
|
7
|
+
# this requires Ruby 2.1 and later for "exception: false"
|
8
|
+
module Yahns::OpenSSLClient # :nodoc:
|
9
|
+
include Yahns::SendfileCompat
|
10
|
+
|
11
|
+
def yahns_init_ssl(ssl_ctx)
|
12
|
+
@need_accept = true
|
13
|
+
@ssl = OpenSSL::SSL::SSLSocket.new(self, ssl_ctx)
|
14
|
+
end
|
15
|
+
|
16
|
+
def kgio_trywrite(buf)
|
17
|
+
rv = @ssl.write_nonblock(buf, exception: false)
|
18
|
+
Integer === rv and
|
19
|
+
rv = buf.bytesize == rv ? nil : buf.byteslice(rv, buf.bytesize)
|
20
|
+
rv
|
21
|
+
end
|
22
|
+
|
23
|
+
def kgio_syssend(buf, flags)
|
24
|
+
kgio_trywrite(buf)
|
25
|
+
end
|
26
|
+
|
27
|
+
def kgio_tryread(len, buf)
|
28
|
+
if @need_accept
|
29
|
+
# most protocols require read before write, so we start the negotiation
|
30
|
+
# process here:
|
31
|
+
begin
|
32
|
+
@ssl.accept_nonblock
|
33
|
+
rescue IO::WaitReadable
|
34
|
+
return :wait_readable
|
35
|
+
rescue IO::WaitWritable
|
36
|
+
return :wait_writable
|
37
|
+
rescue OpenSSL::SSL::SSLError
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
@need_accept = false
|
41
|
+
end
|
42
|
+
@ssl.read_nonblock(len, buf, exception: false)
|
43
|
+
end
|
44
|
+
|
45
|
+
def shutdown(*args)
|
46
|
+
@ssl.shutdown(*args)
|
47
|
+
super # BasicSocket#shutdown
|
48
|
+
end
|
49
|
+
|
50
|
+
def close
|
51
|
+
@ssl.close
|
52
|
+
super # IO#close
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright (C) 2014, all contributors <yahns-public@yhbt.net>
|
2
|
+
# License: GPLv3 or later (see COPYING for details)
|
3
|
+
|
4
|
+
require_relative 'acceptor'
|
5
|
+
require_relative 'openssl_client'
|
6
|
+
|
7
|
+
class Yahns::OpenSSLServer < Kgio::TCPServer # :nodoc:
|
8
|
+
include Yahns::Acceptor
|
9
|
+
|
10
|
+
def self.wrap(fd, ssl_ctx)
|
11
|
+
srv = for_fd(fd)
|
12
|
+
srv.instance_variable_set(:@ssl_ctx, ssl_ctx)
|
13
|
+
srv
|
14
|
+
end
|
15
|
+
|
16
|
+
def kgio_accept(klass, flags)
|
17
|
+
io = super
|
18
|
+
io.yahns_init_ssl(@ssl_ctx)
|
19
|
+
io
|
20
|
+
end
|
21
|
+
end
|
data/lib/yahns/rackup_handler.rb
CHANGED
@@ -18,8 +18,8 @@ module Yahns::RackupHandler # :nodoc:
|
|
18
18
|
app(:rack, app) do
|
19
19
|
addr = o[:listen] || "#{o[:Host]||default_host}:#{o[:Port]||8080}"
|
20
20
|
# allow listening to multiple addresses
|
21
|
-
if addr
|
22
|
-
addr.split(
|
21
|
+
if addr.include?(',')
|
22
|
+
addr.split(',').each { |l| listen(l) }
|
23
23
|
else
|
24
24
|
listen addr
|
25
25
|
end
|
@@ -1,25 +1,23 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
# Copyright (C) 2009-2014, Eric Wong <normalperson@yhbt.net> et. al.
|
3
3
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
-
require 'io/extra' # gem install io-extra
|
5
4
|
|
6
5
|
module Yahns::SendfileCompat
|
7
6
|
def trysendfile(io, offset, count)
|
8
7
|
return 0 if count == 0
|
9
8
|
count = 0x4000 if count > 0x4000
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
buf = Thread.current[:yahns_sfbuf] ||= ''
|
10
|
+
io.pos = offset
|
11
|
+
str = io.read(count, buf) or return # nil for EOF
|
14
12
|
n = 0
|
15
13
|
case rv = kgio_trywrite(str)
|
16
14
|
when String # partial write, keep trying
|
17
|
-
n += (str.
|
15
|
+
n += (str.size - rv.size)
|
18
16
|
str = rv
|
19
17
|
when :wait_writable, :wait_readable
|
20
18
|
return n > 0 ? n : rv
|
21
19
|
when nil
|
22
|
-
return n + str.
|
20
|
+
return n + str.size # yay!
|
23
21
|
end while true
|
24
22
|
end
|
25
23
|
end
|
data/lib/yahns/server.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
3
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
3
|
require_relative 'queue_quitter'
|
@@ -178,10 +177,9 @@ class Yahns::Server # :nodoc:
|
|
178
177
|
tries = 5
|
179
178
|
|
180
179
|
begin
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
180
|
+
opts = sock_opts(address)
|
181
|
+
io = bind_listen(address, opts)
|
182
|
+
io = server_cast(io, opts) unless io.class.name.start_with?('Yahns::')
|
185
183
|
@logger.info "listening on addr=#{sock_name(io)} fd=#{io.fileno}"
|
186
184
|
@listeners << io
|
187
185
|
io
|
@@ -299,7 +297,7 @@ class Yahns::Server # :nodoc:
|
|
299
297
|
end
|
300
298
|
|
301
299
|
def sock_opts(io)
|
302
|
-
@config.config_listeners[sock_name(io)]
|
300
|
+
@config.config_listeners[sock_name(io)] || {}
|
303
301
|
end
|
304
302
|
|
305
303
|
def inherit_listeners!
|
@@ -314,11 +312,12 @@ class Yahns::Server # :nodoc:
|
|
314
312
|
# because that can completely break the non-blocking one.
|
315
313
|
# Unfortunately, there is no one-off MSG_DONTWAIT-like flag for
|
316
314
|
# accept4(2).
|
317
|
-
inherited = ENV['YAHNS_FD'].to_s.split(
|
315
|
+
inherited = ENV['YAHNS_FD'].to_s.split(',').map! do |fd|
|
318
316
|
io = Socket.for_fd(fd.to_i)
|
319
|
-
|
317
|
+
opts = sock_opts(io)
|
318
|
+
set_server_sockopt(io, opts)
|
320
319
|
@logger.info "inherited addr=#{sock_name(io)} fd=#{fd}"
|
321
|
-
server_cast(io)
|
320
|
+
server_cast(io, opts)
|
322
321
|
end
|
323
322
|
|
324
323
|
@listeners.replace(inherited)
|
@@ -369,6 +368,7 @@ class Yahns::Server # :nodoc:
|
|
369
368
|
ctx.queue = queues[qegg] ||= qegg_vivify(qegg, fdmap)
|
370
369
|
ctx = ctx.dup
|
371
370
|
ctx.__send__(:include, l.expire_mod)
|
371
|
+
ctx.__send__(:include, Yahns::OpenSSLClient) if opts[:ssl_ctx]
|
372
372
|
ctx_list << ctx
|
373
373
|
# acceptors feed the the queues
|
374
374
|
l.spawn_acceptor(opts[:threads] || 1, @logger, ctx)
|
data/lib/yahns/socket_helper.rb
CHANGED
@@ -16,7 +16,7 @@ module Yahns::SocketHelper # :nodoc:
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def set_server_sockopt(sock, opt)
|
19
|
-
opt = {backlog: 1024}.merge!(opt
|
19
|
+
opt = {backlog: 1024}.merge!(opt)
|
20
20
|
sock.close_on_exec = true
|
21
21
|
|
22
22
|
TCPSocket === sock and sock.setsockopt(:IPPROTO_TCP, :TCP_NODELAY, 1)
|
@@ -97,7 +97,12 @@ module Yahns::SocketHelper # :nodoc:
|
|
97
97
|
|
98
98
|
sock.bind(Socket.pack_sockaddr_in(port, addr))
|
99
99
|
sock.autoclose = false
|
100
|
-
|
100
|
+
|
101
|
+
if ssl_ctx = opt[:ssl_ctx]
|
102
|
+
Yahns::OpenSSLServer.wrap(sock.fileno, ssl_ctx)
|
103
|
+
else
|
104
|
+
Yahns::TCPServer.for_fd(sock.fileno)
|
105
|
+
end
|
101
106
|
end
|
102
107
|
|
103
108
|
# returns rfc2732-style (e.g. "[::1]:666") addresses for IPv6
|
@@ -128,11 +133,15 @@ module Yahns::SocketHelper # :nodoc:
|
|
128
133
|
end
|
129
134
|
|
130
135
|
# casts a given Socket to be a TCPServer or UNIXServer
|
131
|
-
def server_cast(sock)
|
136
|
+
def server_cast(sock, opts)
|
132
137
|
sock.autoclose = false
|
133
138
|
begin
|
134
139
|
Socket.unpack_sockaddr_in(sock.getsockname)
|
135
|
-
|
140
|
+
if ssl_ctx = opts[:ssl_ctx]
|
141
|
+
Yahns::OpenSSLServer.wrap(sock.fileno, ssl_ctx)
|
142
|
+
else
|
143
|
+
Yahns::TCPServer.for_fd(sock.fileno)
|
144
|
+
end
|
136
145
|
rescue ArgumentError
|
137
146
|
Yahns::UNIXServer.for_fd(sock.fileno)
|
138
147
|
end
|
data/lib/yahns/tmpio.rb
CHANGED
@@ -14,7 +14,7 @@ class Yahns::TmpIO < File # :nodoc:
|
|
14
14
|
def self.new(tmpdir = Dir.tmpdir)
|
15
15
|
retried = false
|
16
16
|
begin
|
17
|
-
fp = super("#{tmpdir}/#{rand}", RDWR|CREAT|EXCL, 0600)
|
17
|
+
fp = super("#{tmpdir}/#{rand}", RDWR|CREAT|EXCL|APPEND, 0600)
|
18
18
|
rescue Errno::EEXIST
|
19
19
|
retry
|
20
20
|
rescue Errno::EMFILE, Errno::ENFILE
|
data/lib/yahns/wbuf_common.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
# Copyright (C) 2009-2013, Eric Wong <normalperson@yhbt.net> et. al.
|
3
3
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
-
|
5
|
-
|
6
|
-
else
|
4
|
+
begin
|
5
|
+
raise LoadError, "SENDFILE_BROKEN env set" if ENV["SENDFILE_BROKEN"]
|
7
6
|
require 'sendfile'
|
7
|
+
rescue LoadError
|
8
|
+
require_relative 'sendfile_compat'
|
8
9
|
end
|
9
10
|
|
10
11
|
module Yahns::WbufCommon # :nodoc:
|
@@ -32,6 +33,9 @@ module Yahns::WbufCommon # :nodoc:
|
|
32
33
|
"sf_offset=#@sf_offset sf_count=#@sf_count"
|
33
34
|
end while @sf_count > 0
|
34
35
|
wbuf_close(client)
|
36
|
+
rescue
|
37
|
+
wbuf_close(client)
|
38
|
+
raise
|
35
39
|
end
|
36
40
|
|
37
41
|
def wbuf_close_common(client)
|
data/test/server_helper.rb
CHANGED
@@ -61,9 +61,9 @@ module ServerHelper
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def server_helper_teardown
|
64
|
-
@srv.close
|
65
|
-
@ru.close! if @ru
|
66
|
-
check_err
|
64
|
+
@srv.close if defined?(@srv) && !@srv.closed?
|
65
|
+
@ru.close! if defined?(@ru) && @ru
|
66
|
+
check_err if defined?(@err)
|
67
67
|
end
|
68
68
|
|
69
69
|
def server_helper_setup
|
data/test/test_serve_static.rb
CHANGED
@@ -85,6 +85,67 @@ class TestServeStatic < Testcase
|
|
85
85
|
[ off + 1, sparse ]
|
86
86
|
end
|
87
87
|
|
88
|
+
class ToPathClose
|
89
|
+
attr_reader :closed_p
|
90
|
+
|
91
|
+
def initialize(app, tmpdir)
|
92
|
+
@app = app
|
93
|
+
@tmpdir = tmpdir
|
94
|
+
@log = "#@tmpdir/to_path--close"
|
95
|
+
@body = nil
|
96
|
+
@closed_p = false
|
97
|
+
end
|
98
|
+
|
99
|
+
def call(env)
|
100
|
+
s, h, b = @app.call(env)
|
101
|
+
@body = b
|
102
|
+
[ s, h, self ]
|
103
|
+
end
|
104
|
+
|
105
|
+
def each
|
106
|
+
raise "ToPathClose#each should not be called"
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_path
|
110
|
+
File.open(@log, "a") { |fp| fp.write("to_path\n") }
|
111
|
+
"#@tmpdir/sparse"
|
112
|
+
end
|
113
|
+
|
114
|
+
def close
|
115
|
+
File.open(@log, "a") { |fp| fp.write("close\n") }
|
116
|
+
raise "Double close" if @closed_p
|
117
|
+
@closed_p = true
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_aborted_sendfile_closes_opened_path
|
123
|
+
tmpdir = Dir.mktmpdir
|
124
|
+
mksparse(tmpdir)
|
125
|
+
fifo = "#{tmpdir}/to_path--close"
|
126
|
+
assert system("mkfifo", fifo), "mkfifo"
|
127
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
128
|
+
pid = mkserver(cfg) do
|
129
|
+
cfg.instance_eval do
|
130
|
+
app = Rack::Builder.new do
|
131
|
+
use ToPathClose, tmpdir
|
132
|
+
run Rack::File.new(tmpdir)
|
133
|
+
end
|
134
|
+
app(:rack, app) { listen "#{host}:#{port}" }
|
135
|
+
stderr_path err.path
|
136
|
+
end
|
137
|
+
end
|
138
|
+
c = get_tcp_client(host, port)
|
139
|
+
c.write "GET /sparse HTTP/1.1\r\nHost: example.com\r\n\r\n"
|
140
|
+
assert_equal "to_path\n", File.read(fifo)
|
141
|
+
wait_for_full(c)
|
142
|
+
assert_nil c.close
|
143
|
+
Timeout.timeout(30) { assert_equal "close\n", File.read(fifo) }
|
144
|
+
ensure
|
145
|
+
quit_wait(pid)
|
146
|
+
FileUtils.rm_rf(tmpdir)
|
147
|
+
end
|
148
|
+
|
88
149
|
def test_truncated_sendfile
|
89
150
|
tmpdir = Dir.mktmpdir
|
90
151
|
size, sparse = mksparse(tmpdir)
|
data/test/test_ssl.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (C) 2014, all contributors <yahns-public@yhbt.net>
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require_relative 'server_helper'
|
4
|
+
require 'openssl'
|
5
|
+
class TestSSL < Testcase
|
6
|
+
ENV["N"].to_i > 1 and parallelize_me!
|
7
|
+
include ServerHelper
|
8
|
+
|
9
|
+
r, w = IO.pipe
|
10
|
+
FAST_NB = begin
|
11
|
+
:wait_readable == r.read_nonblock(1, exception: false)
|
12
|
+
rescue
|
13
|
+
false
|
14
|
+
end
|
15
|
+
r.close
|
16
|
+
w.close
|
17
|
+
|
18
|
+
# copied from test/openssl/utils.rb in Ruby:
|
19
|
+
|
20
|
+
TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_
|
21
|
+
-----BEGIN DH PARAMETERS-----
|
22
|
+
MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
|
23
|
+
pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
|
24
|
+
AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
|
25
|
+
-----END DH PARAMETERS-----
|
26
|
+
_end_of_pem_
|
27
|
+
|
28
|
+
TEST_KEY_DH1024.priv_key = OpenSSL::BN.new("48561834C67E65FFD2A9B47F41" \
|
29
|
+
"E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2" \
|
30
|
+
"CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB4" \
|
31
|
+
"51E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672E" \
|
32
|
+
"EF3EF13AB47A15275FC2836F3AC74CEA", 16)
|
33
|
+
|
34
|
+
def setup
|
35
|
+
unless FAST_NB
|
36
|
+
skip "missing exception-free non-blocking IO in " \
|
37
|
+
"#{RUBY_ENGINE} #{RUBY_VERSION}"
|
38
|
+
end
|
39
|
+
server_helper_setup
|
40
|
+
end
|
41
|
+
|
42
|
+
def teardown
|
43
|
+
server_helper_teardown
|
44
|
+
end
|
45
|
+
|
46
|
+
def ssl_client(host, port)
|
47
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
48
|
+
ctx.ciphers = "ADH"
|
49
|
+
s = TCPSocket.new(host, port)
|
50
|
+
ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
|
51
|
+
ssl.connect
|
52
|
+
ssl.sync_close = true
|
53
|
+
ssl
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_ssl_basic
|
57
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
58
|
+
host, port = @srv.addr[3], @srv.addr[1]
|
59
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
60
|
+
ctx.ciphers = "ADH"
|
61
|
+
ctx.tmp_dh_callback = proc { TEST_KEY_DH1024 }
|
62
|
+
|
63
|
+
pid = mkserver(cfg) do
|
64
|
+
cfg.instance_eval do
|
65
|
+
ru = lambda { |_| [ 200, {'Content-Length'=>'2'}, ['HI'] ] }
|
66
|
+
app(:rack, ru) { listen "#{host}:#{port}", ssl_ctx: ctx }
|
67
|
+
logger(Logger.new(err.path))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
client = ssl_client(host, port)
|
71
|
+
client.write("GET / HTTP/1.0\r\n\r\n")
|
72
|
+
head, body = client.read.split("\r\n\r\n", 2)
|
73
|
+
assert_equal "HI", body
|
74
|
+
assert_match %r{\AHTTP/1\.\d 200 OK\r\n}, head
|
75
|
+
ensure
|
76
|
+
client.close if client
|
77
|
+
quit_wait(pid)
|
78
|
+
end
|
79
|
+
end if defined?(OpenSSL)
|
data/yahns.gemspec
CHANGED
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.files = manifest
|
13
13
|
s.add_dependency(%q<kgio>, '~> 2.9')
|
14
14
|
s.add_dependency(%q<sleepy_penguin>, '~> 3.2')
|
15
|
-
s.add_dependency(%q<kgio-sendfile>, '~> 1.2')
|
16
15
|
s.add_dependency(%q<unicorn>, '~> 4.6', '>= 4.6.3')
|
16
|
+
# s.add_dependency(%q<kgio-sendfile>, '~> 1.2') # optional
|
17
17
|
|
18
18
|
# minitest is standard in Ruby 2.0, 4.3 is packaged with Ruby 2.0.0,
|
19
19
|
# 4.7.5 with 2.1. We work with minitest 5, too. 6.x does not exist
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yahns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yahns hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.2'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: kgio-sendfile
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.2'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.2'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: unicorn
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,6 +135,8 @@ files:
|
|
149
135
|
- lib/yahns/max_body.rb
|
150
136
|
- lib/yahns/max_body/rewindable_wrapper.rb
|
151
137
|
- lib/yahns/max_body/wrapper.rb
|
138
|
+
- lib/yahns/openssl_client.rb
|
139
|
+
- lib/yahns/openssl_server.rb
|
152
140
|
- lib/yahns/queue.rb
|
153
141
|
- lib/yahns/queue_egg.rb
|
154
142
|
- lib/yahns/queue_epoll.rb
|
@@ -201,6 +189,7 @@ files:
|
|
201
189
|
- test/test_response.rb
|
202
190
|
- test/test_serve_static.rb
|
203
191
|
- test/test_server.rb
|
192
|
+
- test/test_ssl.rb
|
204
193
|
- test/test_stream_file.rb
|
205
194
|
- test/test_unix_socket.rb
|
206
195
|
- test/test_wbuf.rb
|
@@ -225,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
225
214
|
version: '0'
|
226
215
|
requirements: []
|
227
216
|
rubyforge_project:
|
228
|
-
rubygems_version: 2.4.
|
217
|
+
rubygems_version: 2.4.5
|
229
218
|
signing_key:
|
230
219
|
specification_version: 4
|
231
220
|
summary: sleepy, multi-threaded, non-blocking application server
|