Class: Waitress::HttpServer
- Inherits:
-
Array
- Object
- Array
- Waitress::HttpServer
- Defined in:
- lib/waitress/server.rb
Overview
The Waitress HTTPServer. This class is responsible for handling traffic from clients and delegating it to the correct Virtual Host to further handle. New threads and Processes are spawned for each connection to the server
Defined Under Namespace
Classes: HttpParams
Instance Attribute Summary collapse
-
#processes ⇒ Object
Returns the value of attribute processes.
Instance Method Summary collapse
- #build_request(headers, client_socket) ⇒ Object
- #connect_client(client) ⇒ Object
- #handle_client(client_socket) ⇒ Object
- #handle_request(request, client) ⇒ Object
-
#initialize(*ports) ⇒ HttpServer
constructor
Create a new Server instance with the given ports.
-
#join ⇒ Object
Join the server, blocking the current thread in order to keep the server alive.
-
#killall ⇒ Object
Killall running processes.
- #launch_port(port) ⇒ Object
-
#ports(*ports) ⇒ Object
Set or Get the ports for this server.
-
#read_io(io) ⇒ Object
Handle a client based on an IO stream, if you plan to serve on a non-socket connection.
-
#run(*ports) ⇒ Object
Start the server.
-
#set_processes(count) ⇒ Object
Set the amount of concurrent Waitress Processes to run on this Server, per Port.
Constructor Details
#initialize(*ports) ⇒ HttpServer
Create a new Server instance with the given ports. If no ports are given, port 80 will be used as a default
19 20 21 22 23 24 25 |
# File 'lib/waitress/server.rb', line 19 def initialize(*ports) ports << 80 if ports.length == 0 @ports = ports @processes = 5 @processes = ENV["WAITRESS_PROCESSES"].to_i if ENV.include? "WAITRESS_PROCESSES" @running_processes = [] end |
Instance Attribute Details
#processes ⇒ Object
Returns the value of attribute processes.
15 16 17 |
# File 'lib/waitress/server.rb', line 15 def processes @processes end |
Instance Method Details
#build_request(headers, client_socket) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/waitress/server.rb', line 132 def build_request headers, client_socket request_headers = {} headers.each do |k,v| if k.start_with? "HTTP_HEAD_" request_headers[k.sub(/HTTP_HEAD_/, "")] = v end end request = Waitress::Request.new( headers["REQUEST_METHOD"], headers["REQUEST_PATH"], headers["REQUEST_URI"], headers["QUERY_STRING"], headers["HTTP_VERSION"], headers.http_body, request_headers ) handle_request request, client_socket end |
#connect_client(client) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/waitress/server.rb', line 91 def connect_client client begin gofork do # Makes sure requires etc don't get triggered across requests handle_client client end.wait client.close rescue nil rescue => e puts "Server Error: #{e} (Fix This!)" puts e.backtrace client.close rescue nil end end |
#handle_client(client_socket) ⇒ Object
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 130 |
# File 'lib/waitress/server.rb', line 104 def handle_client client_socket begin data = client_socket.readpartial(8192) nparsed = 0 parser = Waitress::HttpParser.new params = HttpParams.new while nparsed < data.length nparsed = parser.execute(params, data, nparsed) if parser.finished? build_request params, client_socket else ch = client.readpartial(8192) break if !ch or ch.length == 0 data << ch end end rescue EOFError, Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL, Errno::EBADF client_socket.close rescue nil rescue => e puts "Client Error: #{e}" puts e.backtrace end client_socket.close rescue nil end |
#handle_request(request, client) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/waitress/server.rb', line 146 def handle_request request, client match, pri = self[0], nil self.each do |vhost| if (request.headers['Host'].to_s =~ vhost.domain) != nil match = vhost if pri.nil? || vhost.priority > pri end end if match.nil? # Subdomain not found (or default) else match.handle_request request, client end end |
#join ⇒ Object
Join the server, blocking the current thread in order to keep the server alive.
62 63 64 |
# File 'lib/waitress/server.rb', line 62 def join @running_processes.each { |x| x.wait } end |
#killall ⇒ Object
Killall running processes
57 58 59 |
# File 'lib/waitress/server.rb', line 57 def killall @running_processes.each { |x| x.kill rescue nil } end |
#launch_port(port) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/waitress/server.rb', line 73 def launch_port port serv = TCPServer.new port processes = [] @processes.times do processes << gofork { while true client = serv.accept connect_client(client) end } end processes.each do |pr| Process.detach(pr.pid) end processes end |
#ports(*ports) ⇒ Object
Set or Get the ports for this server. If arguments are provided, the ports for this server will be replaced with the ones listed. If no arguments are provided, this method simply returns the ports
35 36 37 38 |
# File 'lib/waitress/server.rb', line 35 def ports *ports @ports = *ports unless ports.length == 0 @ports end |
#read_io(io) ⇒ Object
Handle a client based on an IO stream, if you plan to serve on a non-socket connection
68 69 70 |
# File 'lib/waitress/server.rb', line 68 def read_io io handle_client io end |
#run(*ports) ⇒ Object
Start the server. If arguments are provided, it will run with the ports declared in the arguments, otherwise, it will use the ports it already has set (or 80 for the default)
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/waitress/server.rb', line 43 def run *ports @ports = ports unless ports.length == 0 self.each do |vhost| vhost.on_server_start self end @running_processes = @ports.map do |port| launch_port(port) end @running_processes.flatten! self end |
#set_processes(count) ⇒ Object
Set the amount of concurrent Waitress Processes to run on this Server, per Port
28 29 30 |
# File 'lib/waitress/server.rb', line 28 def set_processes count @processes = count end |