Class: Waitress::HttpServer

Inherits:
Array
  • Object
show all
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

Instance Method Summary collapse

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
26
# File 'lib/waitress/server.rb', line 19

def initialize(*ports)
  Waitress::SERVERS << self
  ports << 80 if ports.length == 0
  @ports = ports
  @processes = 10
  @processes = ENV["WAITRESS_PROCESSES"].to_i if ENV.include? "WAITRESS_PROCESSES"
  @running_processes = []
end

Instance Attribute Details

#processesObject

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



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/waitress/server.rb', line 125

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

#handle_client(client_socket) ⇒ Object



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
# File 'lib/waitress/server.rb', line 94

def handle_client client_socket
  # pro = gofork do
  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
  # end
  client_socket.close rescue nil
  # pro.wait
end

#handle_request(request, client) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/waitress/server.rb', line 139

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

#joinObject

Join the server, blocking the current thread in order to keep the server alive.



63
64
65
# File 'lib/waitress/server.rb', line 63

def join
  @running_processes.each { |x| x.wait }
end

#killallObject

Killall running processes



58
59
60
# File 'lib/waitress/server.rb', line 58

def killall
  @running_processes.each { |x| x.kill rescue nil }
end

#launch_port(port) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/waitress/server.rb', line 74

def launch_port port
  serv = TCPServer.new port
  processes = []
  @processes.times do
    processes << gofork {
      while true
        begin
          client = serv.accept
          handle_client client
        rescue => e
          puts "Server Error: #{e} (Fix This!)"
          puts e.backtrace
          client.close rescue nil
        end
      end
    }
  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



36
37
38
39
# File 'lib/waitress/server.rb', line 36

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



69
70
71
# File 'lib/waitress/server.rb', line 69

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)



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/waitress/server.rb', line 44

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



29
30
31
# File 'lib/waitress/server.rb', line 29

def set_processes count
  @processes = count
end