waitress-core 0.2.4 → 0.3.0

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/LICENSE +21 -21
  4. data/Rakefile +17 -17
  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.rb +100 -99
  17. data/lib/waitress/chef.rb +113 -113
  18. data/lib/waitress/configure.rb +127 -121
  19. data/lib/waitress/evalbind.rb +9 -9
  20. data/lib/waitress/handlers/dirhandler.rb +39 -39
  21. data/lib/waitress/handlers/handler.rb +57 -57
  22. data/lib/waitress/handlers/handler404.rb +25 -25
  23. data/lib/waitress/handlers/libhandler.rb +135 -58
  24. data/lib/waitress/kernel.rb +189 -189
  25. data/lib/waitress/parse/query.rb +60 -60
  26. data/lib/waitress/request.rb +45 -45
  27. data/lib/waitress/resources/default_config.rb +52 -52
  28. data/lib/waitress/resources/default_less.yml +7 -0
  29. data/lib/waitress/resources/http/404.html +18 -18
  30. data/lib/waitress/resources/http/css/hack.css +37 -37
  31. data/lib/waitress/resources/http/css/waitress.css +57 -57
  32. data/lib/waitress/resources/http/fonts/eot/latin/hack-bold-latin-webfont.eot +0 -0
  33. data/lib/waitress/resources/http/fonts/eot/latin/hack-bolditalic-latin-webfont.eot +0 -0
  34. data/lib/waitress/resources/http/fonts/eot/latin/hack-italic-latin-webfont.eot +0 -0
  35. data/lib/waitress/resources/http/fonts/eot/latin/hack-regular-latin-webfont.eot +0 -0
  36. data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +240 -240
  37. data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +240 -240
  38. data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +240 -240
  39. data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +240 -240
  40. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bold-latin-webfont.ttf +0 -0
  41. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf +0 -0
  42. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-italic-latin-webfont.ttf +0 -0
  43. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-regular-latin-webfont.ttf +0 -0
  44. data/lib/waitress/resources/http/fonts/woff/latin/hack-bold-latin-webfont.woff +0 -0
  45. data/lib/waitress/resources/http/fonts/woff/latin/hack-bolditalic-latin-webfont.woff +0 -0
  46. data/lib/waitress/resources/http/fonts/woff/latin/hack-italic-latin-webfont.woff +0 -0
  47. data/lib/waitress/resources/http/fonts/woff/latin/hack-regular-latin-webfont.woff +0 -0
  48. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bold-latin-webfont.woff2 +0 -0
  49. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2 +0 -0
  50. data/lib/waitress/resources/http/fonts/woff2/latin/hack-italic-latin-webfont.woff2 +0 -0
  51. data/lib/waitress/resources/http/fonts/woff2/latin/hack-regular-latin-webfont.woff2 +0 -0
  52. data/lib/waitress/resources/http/img/404.png +0 -0
  53. data/lib/waitress/resources/http/index.html +15 -15
  54. data/lib/waitress/response.rb +105 -105
  55. data/lib/waitress/server.rb +160 -160
  56. data/lib/waitress/util/less_watcher.rb +56 -0
  57. data/lib/waitress/{util.rb → util/util.rb} +707 -707
  58. data/lib/waitress/version.rb +3 -3
  59. data/lib/waitress/vhost.rb +229 -227
  60. data/lib/waitress_http11.so +0 -0
  61. data/waitress-core.gemspec +32 -29
  62. metadata +48 -4
  63. data/lib/waitress_http11.bundle +0 -0
File without changes
@@ -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,160 +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
- 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
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