waitress-core 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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