Class: ProxyRole
Constant Summary
collapse
- PORT =
9400
- ESI_MATCH =
/<esi:try>.*?<esi:attempt>.*?<esi:include src="([^"]+)" ?\/>.*?<\/esi:attempt>.*?<esi:except>(.*?)<\/esi:except>.*?<\/esi:try>/m
Constants inherited
from Role
Role::INDEX
Instance Method Summary
collapse
Methods inherited from Role
#disable_link, #enable_link, get_role, #init_links, role, #state
Constructor Details
#initialize(manifest) ⇒ ProxyRole
Returns a new instance of ProxyRole.
9
10
11
12
13
|
# File 'lib/proxy_role.rb', line 9
def initialize(manifest)
super
init_links 'backends', @manifest['backends']
init_links 'stats_backends', @manifest['stats_backends']
end
|
Instance Method Details
#choose_backend(request) ⇒ Object
15
16
17
18
19
20
21
22
23
24
25
|
# File 'lib/proxy_role.rb', line 15
def choose_backend(request)
url = request.match(/^[A-Z]+ (.*?) HTTP/)[1]
case url
when /^\/stats/
addr = @active_links['stats_backends'].sort_by { rand }.pop
[addr, StatsRole::PORT] if addr
else
addr = @active_links['backends'].sort_by { rand }.pop
[addr, RailsRole::PORT] if addr
end
end
|
#handle_esi(body) ⇒ Object
29
30
31
32
33
34
35
36
37
|
# File 'lib/proxy_role.rb', line 29
def handle_esi(body)
body.gsub(ESI_MATCH) do |match|
url = $1
otherwise = $2
html = simulate_request($1) || ''
html.strip.size > 0 ? html : otherwise
end
end
|
#simulate_request(url) ⇒ Object
39
40
41
42
|
# File 'lib/proxy_role.rb', line 39
def simulate_request(url)
puts "Simulating request to #{url}"
Net::HTTP.get(URI.parse("http://127.0.0.1:#{PORT}#{url}"))
end
|
#start ⇒ Object
Also known as:
enable
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
|
# File 'lib/proxy_role.rb', line 44
def start
@server_thread = Thread.new {
@proxy_server = TCPServer.new('0.0.0.0', PORT)
loop do
Thread.new(@proxy_server.accept) { |client_sock|
begin
request = client_sock.recv(16384)
backend_addr = choose_backend(request)
if backend_addr
backend_sock = TCPSocket.new(*backend_addr)
backend_sock.send(request, 0)
first_blob = backend_sock.recv(16384)
, body = first_blob.split("\r\n\r\n")
body ||= ''
match = .match(/Content-Length: (\d+)/)
content_length = match ? match[1].to_i : 0
if content_length > 0
if content_length > body.size
body << backend_sock.recv(content_length - body.size)
end
processed_body = handle_esi(body)
real_length = processed_body.size
= .gsub(/Content-Length: (\d+)/, "Content-Length: #{real_length}")
client_sock.send(, 0)
client_sock.send("\r\n\r\n", 0)
client_sock.send(processed_body, 0)
else
client_sock.send(first_blob,0)
end
else
client_sock.send "HTTP/1.1 503 Service Unavailable\r\n\r\n", 0
end
rescue Errno::ECONNREFUSED, Errno::ECONNABORTED
client_sock.send "HTTP/1.1 503 Service Unavailable\r\n\r\n", 0
ensure
backend_sock.close if backend_sock
client_sock.close if client_sock
end
}
end
}
end
|
#stop ⇒ Object
Also known as:
disable
99
100
101
102
103
104
105
106
|
# File 'lib/proxy_role.rb', line 99
def stop
begin
@proxy_server.shutdown if @proxy_server
rescue Errno::ENOTCONN
end
@server_thread.kill if @server_thread
@health_thread.kill if @health_thread
end
|