-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.ru
129 lines (103 loc) · 2.69 KB
/
config.ru
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
require 'rack/app'
require 'pg'
require 'sequel'
db = Sequel.connect("postgres://postgres@localhost:5432")
app = lambda do |_env|
db["SELECT 1=1;"]
resp = Rack::Response.new
resp.write('OK')
resp.finish
end
require 'csv'
require 'socket'
require 'timeout'
require 'rack/content_length'
require 'rack/rewindable_input'
module Rack::App::Handler
::Rack::Handler.register 'rack-app-receiver', 'Rack::App::Handler'
require 'socket'
class Server
def initialize(app, port)
@port = port.to_i
@app = app
@wip = {}
end
def start
@server = ::TCPServer.new(@port)
@wip.clear
loop do
thr = Thread.start(@server.accept) do |s|
handle(s)
@wip.delete(Thread.current.__id__)
end
@wip[thr.__id__] = nil
end
rescue IOError, Errno::EBADF
@server.close unless @server.closed?
end
def stop
sleep(0.1) until @wip.empty?
@server && @server.close
end
private
def handle(socket)
env = receive_env(socket)
resp = response_for(env)
send_headers(socket, resp[0], resp[1])
send_body(socket, resp[2])
ensure
socket.flush
socket.close
end
def send_headers(socket, code, headers)
csv = CSV.new(socket, :col_sep => "\t")
csv << [code]
headers.each do |key, value|
csv << [key, value]
end
socket.puts
ensure
socket.flush
end
def send_body(socket, eachable)
eachable.each do |chunk|
c = socket.write(chunk)
puts("<- #{c}") if ENV["RACK_APP_DEBUG"]
end
ensure
socket.flush
end
def response_for(env)
@app.call(env)
rescue Exception => ex
env[::Rack::RACK_ERRORS] << ex.message << "\n"
[500, {}, []]
end
def receive_env(socket)
env = {}
loop do
line = socket.gets
break if line.strip == ''
row = CSV.parse(line, :col_sep => "\t", headers: %i[key value])
env[row[:key].first] = row[:value].first.to_s
end
env.merge!(::Rack::RACK_VERSION => Rack::VERSION,
::Rack::RACK_INPUT => Rack::RewindableInput.new(socket),
::Rack::RACK_ERRORS => $stderr,
::Rack::RACK_MULTITHREAD => true,
::Rack::RACK_MULTIPROCESS => true,
::Rack::RACK_RUNONCE => false,
::Rack::RACK_URL_SCHEME => env['SCHEME'].downcase)
end
end
module_function
def run(app, options)
server = self::Server.new(app, options[:Port] || '9292')
%w[INT TERM].each { |sig| ::Signal.trap(sig) { server.stop } }
server.start
end
def valid_options
{}
end
end
run app