waitress-core 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/LICENSE +21 -21
- data/Rakefile +13 -4
- data/bin/waitress +22 -22
- data/ext/Thanks.md +1 -1
- data/ext/waitress_http11/ext_help.h +15 -15
- data/ext/waitress_http11/extconf.rb +6 -6
- data/ext/waitress_http11/http11.c +532 -532
- data/ext/waitress_http11/http11_parser.c +1216 -1216
- data/ext/waitress_http11/http11_parser.h +49 -49
- data/ext/waitress_http11/http11_parser.java.rl +171 -171
- data/ext/waitress_http11/http11_parser.rl +165 -165
- data/ext/waitress_http11/http11_parser_common.rl +55 -55
- data/ext/waitress_http11/http11_wrb_parser.h +83 -83
- data/lib/waitress/chef.rb +110 -110
- data/lib/waitress/configure.rb +116 -116
- data/lib/waitress/handlers/dirhandler.rb +39 -39
- data/lib/waitress/handlers/handler.rb +57 -57
- data/lib/waitress/handlers/handler404.rb +25 -25
- data/lib/waitress/handlers/libhandler.rb +58 -58
- data/lib/waitress/kernel.rb +182 -182
- data/lib/waitress/parse/query.rb +60 -60
- data/lib/waitress/request.rb +45 -45
- data/lib/waitress/resources/default_config.rb +52 -52
- data/lib/waitress/resources/http/404.html +18 -18
- data/lib/waitress/resources/http/css/hack.css +37 -37
- data/lib/waitress/resources/http/css/waitress.css +57 -57
- data/lib/waitress/resources/http/fonts/eot/latin/hack-bold-latin-webfont.eot +0 -0
- data/lib/waitress/resources/http/fonts/eot/latin/hack-bolditalic-latin-webfont.eot +0 -0
- data/lib/waitress/resources/http/fonts/eot/latin/hack-italic-latin-webfont.eot +0 -0
- data/lib/waitress/resources/http/fonts/eot/latin/hack-regular-latin-webfont.eot +0 -0
- data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +240 -240
- data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +240 -240
- data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +240 -240
- data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +240 -240
- data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bold-latin-webfont.ttf +0 -0
- data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf +0 -0
- data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-italic-latin-webfont.ttf +0 -0
- data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-regular-latin-webfont.ttf +0 -0
- data/lib/waitress/resources/http/fonts/woff/latin/hack-bold-latin-webfont.woff +0 -0
- data/lib/waitress/resources/http/fonts/woff/latin/hack-bolditalic-latin-webfont.woff +0 -0
- data/lib/waitress/resources/http/fonts/woff/latin/hack-italic-latin-webfont.woff +0 -0
- data/lib/waitress/resources/http/fonts/woff/latin/hack-regular-latin-webfont.woff +0 -0
- data/lib/waitress/resources/http/fonts/woff2/latin/hack-bold-latin-webfont.woff2 +0 -0
- data/lib/waitress/resources/http/fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2 +0 -0
- data/lib/waitress/resources/http/fonts/woff2/latin/hack-italic-latin-webfont.woff2 +0 -0
- data/lib/waitress/resources/http/fonts/woff2/latin/hack-regular-latin-webfont.woff2 +0 -0
- data/lib/waitress/resources/http/img/404.png +0 -0
- data/lib/waitress/resources/http/index.html +15 -15
- data/lib/waitress/response.rb +104 -104
- data/lib/waitress/server.rb +126 -115
- data/lib/waitress/util.rb +707 -713
- data/lib/waitress/version.rb +3 -3
- data/lib/waitress/vhost.rb +217 -217
- data/lib/waitress.rb +98 -98
- data/lib/waitress_http11.bundle +0 -0
- data/waitress-core.gemspec +29 -27
- metadata +35 -7
- data/lib/waitress_http11.so +0 -0
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
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>
|
data/lib/waitress/response.rb
CHANGED
@@ -1,104 +1,104 @@
|
|
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
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
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
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/lib/waitress/server.rb
CHANGED
@@ -1,115 +1,126 @@
|
|
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
|
-
# Create a new Server instance with the given ports. If no ports are given,
|
16
|
-
# port 80 will be used as a default
|
17
|
-
def initialize(*ports)
|
18
|
-
ports << 80 if ports.length == 0
|
19
|
-
@ports = ports
|
20
|
-
end
|
21
|
-
|
22
|
-
# Set or Get the ports for this server. If arguments are provided, the ports
|
23
|
-
# for this server will be replaced with the ones listed. If no arguments are provided,
|
24
|
-
# this method simply returns the ports
|
25
|
-
def ports *ports
|
26
|
-
@ports = *ports unless ports.length == 0
|
27
|
-
@ports
|
28
|
-
end
|
29
|
-
|
30
|
-
# Start the server. If arguments are provided, it will run with the ports
|
31
|
-
# declared in the arguments, otherwise, it will use the ports it already has
|
32
|
-
# set (or 80 for the default)
|
33
|
-
def run *ports
|
34
|
-
@ports = ports unless ports.length == 0
|
35
|
-
@threads = @ports.map { |x| Thread.new { launch_port x } }
|
36
|
-
self.each do |vhost|
|
37
|
-
vhost.on_server_start self
|
38
|
-
end
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
# Join the server, blocking the current thread in order to keep the server alive.
|
43
|
-
def join
|
44
|
-
@threads.each { |x| x.join }
|
45
|
-
end
|
46
|
-
|
47
|
-
# Handle a client based on an IO stream, if you plan to serve on a non-socket
|
48
|
-
# connection
|
49
|
-
def read_io io
|
50
|
-
handle_client io
|
51
|
-
end
|
52
|
-
|
53
|
-
:private
|
54
|
-
def launch_port port
|
55
|
-
@server = TCPServer.new port
|
56
|
-
while true
|
57
|
-
client = @server.accept
|
58
|
-
go do
|
59
|
-
begin
|
60
|
-
handle_client client
|
61
|
-
rescue => e
|
62
|
-
puts "Server Error: #{e} (Fix This!)"
|
63
|
-
puts e.backtrace
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def handle_client client_socket
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
+
# Create a new Server instance with the given ports. If no ports are given,
|
16
|
+
# port 80 will be used as a default
|
17
|
+
def initialize(*ports)
|
18
|
+
ports << 80 if ports.length == 0
|
19
|
+
@ports = ports
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set or Get the ports for this server. If arguments are provided, the ports
|
23
|
+
# for this server will be replaced with the ones listed. If no arguments are provided,
|
24
|
+
# this method simply returns the ports
|
25
|
+
def ports *ports
|
26
|
+
@ports = *ports unless ports.length == 0
|
27
|
+
@ports
|
28
|
+
end
|
29
|
+
|
30
|
+
# Start the server. If arguments are provided, it will run with the ports
|
31
|
+
# declared in the arguments, otherwise, it will use the ports it already has
|
32
|
+
# set (or 80 for the default)
|
33
|
+
def run *ports
|
34
|
+
@ports = ports unless ports.length == 0
|
35
|
+
@threads = @ports.map { |x| Thread.new { launch_port x } }
|
36
|
+
self.each do |vhost|
|
37
|
+
vhost.on_server_start self
|
38
|
+
end
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Join the server, blocking the current thread in order to keep the server alive.
|
43
|
+
def join
|
44
|
+
@threads.each { |x| x.join }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Handle a client based on an IO stream, if you plan to serve on a non-socket
|
48
|
+
# connection
|
49
|
+
def read_io io
|
50
|
+
handle_client io
|
51
|
+
end
|
52
|
+
|
53
|
+
:private
|
54
|
+
def launch_port port
|
55
|
+
@server = TCPServer.new port
|
56
|
+
while true
|
57
|
+
client = @server.accept
|
58
|
+
go do
|
59
|
+
begin
|
60
|
+
handle_client client
|
61
|
+
rescue => e
|
62
|
+
puts "Server Error: #{e} (Fix This!)"
|
63
|
+
puts e.backtrace
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def handle_client client_socket
|
70
|
+
gofork do
|
71
|
+
begin
|
72
|
+
data = client_socket.readpartial(8192)
|
73
|
+
nparsed = 0
|
74
|
+
|
75
|
+
parser = Waitress::HttpParser.new
|
76
|
+
params = HttpParams.new
|
77
|
+
|
78
|
+
while nparsed < data.length
|
79
|
+
nparsed = parser.execute(params, data, nparsed)
|
80
|
+
if parser.finished?
|
81
|
+
build_request params, client_socket
|
82
|
+
else
|
83
|
+
ch = client.readpartial(8192)
|
84
|
+
break if !ch or ch.length == 0
|
85
|
+
|
86
|
+
data << ch
|
87
|
+
end
|
88
|
+
end
|
89
|
+
rescue => e
|
90
|
+
puts "Client Error: #{e}"
|
91
|
+
puts e.backtrace
|
92
|
+
end
|
93
|
+
end.wait
|
94
|
+
client_socket.close unless client_socket.closed?
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_request headers, client_socket
|
98
|
+
request_headers = {}
|
99
|
+
headers.each do |k,v|
|
100
|
+
if k.start_with? "HTTP_HEAD_"
|
101
|
+
request_headers[k.sub(/HTTP_HEAD_/, "")] = v
|
102
|
+
end
|
103
|
+
end
|
104
|
+
request = Waitress::Request.new(
|
105
|
+
headers["REQUEST_METHOD"], headers["REQUEST_PATH"], headers["REQUEST_URI"],
|
106
|
+
headers["QUERY_STRING"], headers["HTTP_VERSION"], headers.http_body, request_headers
|
107
|
+
)
|
108
|
+
handle_request request, client_socket
|
109
|
+
end
|
110
|
+
|
111
|
+
def handle_request request, client
|
112
|
+
match, pri = self[0], nil
|
113
|
+
self.each do |vhost|
|
114
|
+
if (request.headers['Host'].to_s =~ vhost.domain) != nil
|
115
|
+
match = vhost if pri.nil? || vhost.priority > pri
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if match.nil?
|
120
|
+
# Subdomain not found (or default)
|
121
|
+
else
|
122
|
+
match.handle_request request, client
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|