waitress-core 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/LICENSE +21 -21
  4. data/Rakefile +13 -13
  5. data/bin/waitress +22 -22
  6. data/ext/Thanks.md +1 -1
  7. data/ext/waitress_http11/ext_help.h +15 -15
  8. data/ext/waitress_http11/extconf.rb +6 -6
  9. data/ext/waitress_http11/http11.c +532 -532
  10. data/ext/waitress_http11/http11_parser.c +1216 -1216
  11. data/ext/waitress_http11/http11_parser.h +49 -49
  12. data/ext/waitress_http11/http11_parser.java.rl +171 -171
  13. data/ext/waitress_http11/http11_parser.rl +165 -165
  14. data/ext/waitress_http11/http11_parser_common.rl +55 -55
  15. data/ext/waitress_http11/http11_wrb_parser.h +91 -91
  16. data/lib/waitress/chef.rb +113 -113
  17. data/lib/waitress/configure.rb +121 -121
  18. data/lib/waitress/evalbind.rb +9 -9
  19. data/lib/waitress/handlers/dirhandler.rb +39 -39
  20. data/lib/waitress/handlers/handler.rb +57 -57
  21. data/lib/waitress/handlers/handler404.rb +25 -25
  22. data/lib/waitress/handlers/libhandler.rb +58 -58
  23. data/lib/waitress/kernel.rb +182 -182
  24. data/lib/waitress/parse/query.rb +60 -60
  25. data/lib/waitress/request.rb +45 -45
  26. data/lib/waitress/resources/default_config.rb +52 -52
  27. data/lib/waitress/resources/http/404.html +18 -18
  28. data/lib/waitress/resources/http/css/hack.css +37 -37
  29. data/lib/waitress/resources/http/css/waitress.css +57 -57
  30. data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +240 -240
  31. data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +240 -240
  32. data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +240 -240
  33. data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +240 -240
  34. data/lib/waitress/resources/http/index.html +15 -15
  35. data/lib/waitress/response.rb +105 -105
  36. data/lib/waitress/server.rb +160 -161
  37. data/lib/waitress/util.rb +707 -707
  38. data/lib/waitress/version.rb +3 -3
  39. data/lib/waitress/vhost.rb +217 -217
  40. data/lib/waitress.rb +99 -106
  41. data/lib/waitress_http11.bundle +0 -0
  42. data/waitress-core.gemspec +29 -29
  43. metadata +4 -4
  44. data/lib/waitress_http11.so +0 -0
@@ -1,15 +1,15 @@
1
- <html>
2
- <head>
3
- <title> Welcome to Waitress </title>
4
- <link rel="stylesheet" href="css/hack.css">
5
- <link rel="stylesheet" href="css/waitress.css">
6
- </head>
7
- <body>
8
- <div id="maincontainer">
9
- <div class="titlecontainer">
10
- <h1> Waitress </h1>
11
- <h2> Please take a seat and let me take your order </h2>
12
- </div>
13
- </div>
14
- </body>
15
- </html>
1
+ <html>
2
+ <head>
3
+ <title> Welcome to Waitress </title>
4
+ <link rel="stylesheet" href="css/hack.css">
5
+ <link rel="stylesheet" href="css/waitress.css">
6
+ </head>
7
+ <body>
8
+ <div id="maincontainer">
9
+ <div class="titlecontainer">
10
+ <h1> Waitress </h1>
11
+ <h2> Please take a seat and let me take your order </h2>
12
+ </div>
13
+ </div>
14
+ </body>
15
+ </html>
@@ -1,105 +1,105 @@
1
- module Waitress
2
- # The response class is used to cook responses to be served to the client.
3
- # This class contains things like response headers, status codes and the response
4
- # body itself
5
- class Response
6
-
7
- def initialize
8
- @headers = {}
9
- status 200
10
- default_headers
11
- @isdone = false
12
- end
13
-
14
- # Returns true if the response has already been sent to the client
15
- def done?
16
- @isdone
17
- end
18
-
19
- # Mark the response as done (already sent to the client)
20
- def done state=true
21
- @isdone = state
22
- end
23
-
24
- # Apply the default headers to this response
25
- def default_headers
26
- header "Server", "Waitress #{Waitress::VERSION} (#{RUBY_PLATFORM})"
27
- end
28
-
29
- # Apply the given Status code to the response, such as 200, 404, 500 or
30
- # any other code listed in the HTTP protocol specification
31
- def status status_code
32
- @status = status_code
33
- @status_msg = Waitress::Util.status @status
34
- header "Status", "#{@status} #{@status_msg}"
35
- end
36
-
37
- # Set the mimetype (Content-Type header) of this response to the one matching
38
- # the given file extension as matched by the +Waitress::Util+ class
39
- # +filext+:: The file extension to match, e.g. .html, .css, .js
40
- def mime filext
41
- m = Waitress::Util.mime filext
42
- header "Content-Type", m
43
- end
44
-
45
- # Set the mimetype (Content-Type header) of this response to the one given.
46
- # +type+:: The mime type to use, e.g. application/json, text/html,
47
- # application/scon
48
- def mime_raw type
49
- header "Content-Type", type
50
- end
51
-
52
- # Set a header for the response. This header will be encoded to the http
53
- # response
54
- # Params:
55
- # +header+:: The name of the header. e.g. "Content-Type"
56
- # +data+:: The data to be encoded into the header. e.g. "text/html"
57
- def header header, data
58
- @headers[header] = data
59
- end
60
-
61
- # Set the Body IO object for the response. This IO object will be read from
62
- # when the webpage is served, so usually this is a File reference or a StringIO
63
- # +io+:: The io object to use. Not required if you just want to get the IO object
64
- def body_io io=:get
65
- @io = io unless io == :get
66
- @io
67
- end
68
-
69
- # Append something to the Body IO. If the Body IO is a StringIO, this will usually be
70
- # a String. This is mostly used for the 'echo' function
71
- def append obj
72
- @io.write obj
73
- end
74
-
75
- # Set the body to be a String. This will replace the BodyIO with a StringIO
76
- # containing the string
77
- # +str+:: The new string to replace the BodyIO with
78
- def body str
79
- body_io StringIO.new(str)
80
- end
81
-
82
- # Serve the response to the given socket. This will write the Headers, Response
83
- # Code and Body.
84
- def serve sock
85
- unless done?
86
- sock.write "HTTP/1.1 #{@status} #{@status_msg}\r\n"
87
- @headers.each do |k, v|
88
- sock.write "#{k}: #{v}\r\n"
89
- end
90
- sock.write "\r\n"
91
- unless @io.nil?
92
- @io.pos = 0
93
- until @io.eof?
94
- s = @io.read(4096)
95
- sock.write s
96
- end
97
- end
98
- done
99
- sock.close rescue nil
100
- @io.close rescue nil
101
- end
102
- end
103
-
104
- end
105
- end
1
+ module Waitress
2
+ # The response class is used to cook responses to be served to the client.
3
+ # This class contains things like response headers, status codes and the response
4
+ # body itself
5
+ class Response
6
+
7
+ def initialize
8
+ @headers = {}
9
+ status 200
10
+ default_headers
11
+ @isdone = false
12
+ end
13
+
14
+ # Returns true if the response has already been sent to the client
15
+ def done?
16
+ @isdone
17
+ end
18
+
19
+ # Mark the response as done (already sent to the client)
20
+ def done state=true
21
+ @isdone = state
22
+ end
23
+
24
+ # Apply the default headers to this response
25
+ def default_headers
26
+ header "Server", "Waitress #{Waitress::VERSION} (#{RUBY_PLATFORM})"
27
+ end
28
+
29
+ # Apply the given Status code to the response, such as 200, 404, 500 or
30
+ # any other code listed in the HTTP protocol specification
31
+ def status status_code
32
+ @status = status_code
33
+ @status_msg = Waitress::Util.status @status
34
+ header "Status", "#{@status} #{@status_msg}"
35
+ end
36
+
37
+ # Set the mimetype (Content-Type header) of this response to the one matching
38
+ # the given file extension as matched by the +Waitress::Util+ class
39
+ # +filext+:: The file extension to match, e.g. .html, .css, .js
40
+ def mime filext
41
+ m = Waitress::Util.mime filext
42
+ header "Content-Type", m
43
+ end
44
+
45
+ # Set the mimetype (Content-Type header) of this response to the one given.
46
+ # +type+:: The mime type to use, e.g. application/json, text/html,
47
+ # application/scon
48
+ def mime_raw type
49
+ header "Content-Type", type
50
+ end
51
+
52
+ # Set a header for the response. This header will be encoded to the http
53
+ # response
54
+ # Params:
55
+ # +header+:: The name of the header. e.g. "Content-Type"
56
+ # +data+:: The data to be encoded into the header. e.g. "text/html"
57
+ def header header, data
58
+ @headers[header] = data
59
+ end
60
+
61
+ # Set the Body IO object for the response. This IO object will be read from
62
+ # when the webpage is served, so usually this is a File reference or a StringIO
63
+ # +io+:: The io object to use. Not required if you just want to get the IO object
64
+ def body_io io=:get
65
+ @io = io unless io == :get
66
+ @io
67
+ end
68
+
69
+ # Append something to the Body IO. If the Body IO is a StringIO, this will usually be
70
+ # a String. This is mostly used for the 'echo' function
71
+ def append obj
72
+ @io.write obj
73
+ end
74
+
75
+ # Set the body to be a String. This will replace the BodyIO with a StringIO
76
+ # containing the string
77
+ # +str+:: The new string to replace the BodyIO with
78
+ def body str
79
+ body_io StringIO.new(str)
80
+ end
81
+
82
+ # Serve the response to the given socket. This will write the Headers, Response
83
+ # Code and Body.
84
+ def serve sock
85
+ unless done?
86
+ sock.write "HTTP/1.1 #{@status} #{@status_msg}\r\n"
87
+ @headers.each do |k, v|
88
+ sock.write "#{k}: #{v}\r\n"
89
+ end
90
+ sock.write "\r\n"
91
+ unless @io.nil?
92
+ @io.pos = 0
93
+ until @io.eof?
94
+ s = @io.read(4096)
95
+ sock.write s
96
+ end
97
+ end
98
+ done
99
+ sock.close rescue nil
100
+ @io.close rescue nil
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -1,161 +1,160 @@
1
- require 'socket'
2
- require 'thread'
3
-
4
- module Waitress
5
-
6
- # The Waitress HTTPServer. This class is responsible for handling traffic from
7
- # clients and delegating it to the correct Virtual Host to further handle.
8
- # New threads and Processes are spawned for each connection to the server
9
- class HttpServer < Array
10
-
11
- class HttpParams < Hash
12
- attr_accessor :http_body
13
- end
14
-
15
- attr_accessor :processes
16
-
17
- # Create a new Server instance with the given ports. If no ports are given,
18
- # port 80 will be used as a default
19
- def initialize(*ports)
20
- Waitress::SERVERS << self
21
- ports << 80 if ports.length == 0
22
- @ports = ports
23
- @processes = 5
24
- @processes = ENV["WAITRESS_PROCESSES"].to_i if ENV.include? "WAITRESS_PROCESSES"
25
- @running_processes = []
26
- end
27
-
28
- # Set the amount of concurrent Waitress Processes to run on this Server, per Port
29
- def set_processes count
30
- @processes = count
31
- end
32
-
33
- # Set or Get the ports for this server. If arguments are provided, the ports
34
- # for this server will be replaced with the ones listed. If no arguments are provided,
35
- # this method simply returns the ports
36
- def ports *ports
37
- @ports = *ports unless ports.length == 0
38
- @ports
39
- end
40
-
41
- # Start the server. If arguments are provided, it will run with the ports
42
- # declared in the arguments, otherwise, it will use the ports it already has
43
- # set (or 80 for the default)
44
- def run *ports
45
- @ports = ports unless ports.length == 0
46
- self.each do |vhost|
47
- vhost.on_server_start self
48
- end
49
-
50
- @running_processes = @ports.map do |port|
51
- launch_port(port)
52
- end
53
- @running_processes.flatten!
54
- self
55
- end
56
-
57
- # Killall running processes
58
- def killall
59
- @running_processes.each { |x| x.kill rescue nil }
60
- end
61
-
62
- # Join the server, blocking the current thread in order to keep the server alive.
63
- def join
64
- @running_processes.each { |x| x.wait }
65
- end
66
-
67
- # Handle a client based on an IO stream, if you plan to serve on a non-socket
68
- # connection
69
- def read_io io
70
- handle_client io
71
- end
72
-
73
- :private
74
- def launch_port port
75
- serv = TCPServer.new port
76
- processes = []
77
- @processes.times do
78
- processes << gofork {
79
- while true
80
- begin
81
- client = serv.accept
82
- gofork do # Makes sure requires etc don't get triggered across requests
83
- handle_client client
84
- end.wait
85
- client.close rescue nil
86
- rescue => e
87
- puts "Server Error: #{e} (Fix This!)"
88
- puts e.backtrace
89
- client.close rescue nil
90
- end
91
- end
92
- }
93
- end
94
-
95
- processes.each do |pr|
96
- Process.detach(pr.pid)
97
- end
98
- processes
99
- end
100
-
101
- def handle_client client_socket
102
- # pro = gofork do
103
- begin
104
- data = client_socket.readpartial(8192)
105
- nparsed = 0
106
-
107
- parser = Waitress::HttpParser.new
108
- params = HttpParams.new
109
-
110
- while nparsed < data.length
111
- nparsed = parser.execute(params, data, nparsed)
112
- if parser.finished?
113
- build_request params, client_socket
114
- else
115
- ch = client.readpartial(8192)
116
- break if !ch or ch.length == 0
117
-
118
- data << ch
119
- end
120
- end
121
- rescue EOFError, Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL, Errno::EBADF
122
- client_socket.close rescue nil
123
- rescue => e
124
- puts "Client Error: #{e}"
125
- puts e.backtrace
126
- end
127
- # end
128
- client_socket.close rescue nil
129
- # pro.wait
130
- end
131
-
132
- def build_request headers, client_socket
133
- request_headers = {}
134
- headers.each do |k,v|
135
- if k.start_with? "HTTP_HEAD_"
136
- request_headers[k.sub(/HTTP_HEAD_/, "")] = v
137
- end
138
- end
139
- request = Waitress::Request.new(
140
- headers["REQUEST_METHOD"], headers["REQUEST_PATH"], headers["REQUEST_URI"],
141
- headers["QUERY_STRING"], headers["HTTP_VERSION"], headers.http_body, request_headers
142
- )
143
- handle_request request, client_socket
144
- end
145
-
146
- def handle_request request, client
147
- match, pri = self[0], nil
148
- self.each do |vhost|
149
- if (request.headers['Host'].to_s =~ vhost.domain) != nil
150
- match = vhost if pri.nil? || vhost.priority > pri
151
- end
152
- end
153
-
154
- if match.nil?
155
- # Subdomain not found (or default)
156
- else
157
- match.handle_request request, client
158
- end
159
- end
160
- end
161
- end
1
+ require 'socket'
2
+ require 'thread'
3
+
4
+ module Waitress
5
+
6
+ # The Waitress HTTPServer. This class is responsible for handling traffic from
7
+ # clients and delegating it to the correct Virtual Host to further handle.
8
+ # New threads and Processes are spawned for each connection to the server
9
+ class HttpServer < Array
10
+
11
+ class HttpParams < Hash
12
+ attr_accessor :http_body
13
+ end
14
+
15
+ attr_accessor :processes
16
+
17
+ # Create a new Server instance with the given ports. If no ports are given,
18
+ # port 80 will be used as a default
19
+ def initialize(*ports)
20
+ ports << 80 if ports.length == 0
21
+ @ports = ports
22
+ @processes = 5
23
+ @processes = ENV["WAITRESS_PROCESSES"].to_i if ENV.include? "WAITRESS_PROCESSES"
24
+ @running_processes = []
25
+ end
26
+
27
+ # Set the amount of concurrent Waitress Processes to run on this Server, per Port
28
+ def set_processes count
29
+ @processes = count
30
+ end
31
+
32
+ # Set or Get the ports for this server. If arguments are provided, the ports
33
+ # for this server will be replaced with the ones listed. If no arguments are provided,
34
+ # this method simply returns the ports
35
+ def ports *ports
36
+ @ports = *ports unless ports.length == 0
37
+ @ports
38
+ end
39
+
40
+ # Start the server. If arguments are provided, it will run with the ports
41
+ # declared in the arguments, otherwise, it will use the ports it already has
42
+ # set (or 80 for the default)
43
+ def run *ports
44
+ @ports = ports unless ports.length == 0
45
+ self.each do |vhost|
46
+ vhost.on_server_start self
47
+ end
48
+
49
+ @running_processes = @ports.map do |port|
50
+ launch_port(port)
51
+ end
52
+ @running_processes.flatten!
53
+ self
54
+ end
55
+
56
+ # Killall running processes
57
+ def killall
58
+ @running_processes.each { |x| x.kill rescue nil }
59
+ end
60
+
61
+ # Join the server, blocking the current thread in order to keep the server alive.
62
+ def join
63
+ @running_processes.each { |x| x.wait }
64
+ end
65
+
66
+ # Handle a client based on an IO stream, if you plan to serve on a non-socket
67
+ # connection
68
+ def read_io io
69
+ handle_client io
70
+ end
71
+
72
+ :private
73
+ def launch_port port
74
+ serv = TCPServer.new port
75
+ processes = []
76
+ @processes.times do
77
+ processes << gofork {
78
+ while true
79
+ begin
80
+ client = serv.accept
81
+ gofork do # Makes sure requires etc don't get triggered across requests
82
+ handle_client client
83
+ end.wait
84
+ client.close rescue nil
85
+ rescue => e
86
+ puts "Server Error: #{e} (Fix This!)"
87
+ puts e.backtrace
88
+ client.close rescue nil
89
+ end
90
+ end
91
+ }
92
+ end
93
+
94
+ processes.each do |pr|
95
+ Process.detach(pr.pid)
96
+ end
97
+ processes
98
+ end
99
+
100
+ def handle_client client_socket
101
+ # pro = gofork do
102
+ begin
103
+ data = client_socket.readpartial(8192)
104
+ nparsed = 0
105
+
106
+ parser = Waitress::HttpParser.new
107
+ params = HttpParams.new
108
+
109
+ while nparsed < data.length
110
+ nparsed = parser.execute(params, data, nparsed)
111
+ if parser.finished?
112
+ build_request params, client_socket
113
+ else
114
+ ch = client.readpartial(8192)
115
+ break if !ch or ch.length == 0
116
+
117
+ data << ch
118
+ end
119
+ end
120
+ rescue EOFError, Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL, Errno::EBADF
121
+ client_socket.close rescue nil
122
+ rescue => e
123
+ puts "Client Error: #{e}"
124
+ puts e.backtrace
125
+ end
126
+ # end
127
+ client_socket.close rescue nil
128
+ # pro.wait
129
+ end
130
+
131
+ def build_request headers, client_socket
132
+ request_headers = {}
133
+ headers.each do |k,v|
134
+ if k.start_with? "HTTP_HEAD_"
135
+ request_headers[k.sub(/HTTP_HEAD_/, "")] = v
136
+ end
137
+ end
138
+ request = Waitress::Request.new(
139
+ headers["REQUEST_METHOD"], headers["REQUEST_PATH"], headers["REQUEST_URI"],
140
+ headers["QUERY_STRING"], headers["HTTP_VERSION"], headers.http_body, request_headers
141
+ )
142
+ handle_request request, client_socket
143
+ end
144
+
145
+ def handle_request request, client
146
+ match, pri = self[0], nil
147
+ self.each do |vhost|
148
+ if (request.headers['Host'].to_s =~ vhost.domain) != nil
149
+ match = vhost if pri.nil? || vhost.priority > pri
150
+ end
151
+ end
152
+
153
+ if match.nil?
154
+ # Subdomain not found (or default)
155
+ else
156
+ match.handle_request request, client
157
+ end
158
+ end
159
+ end
160
+ end