waitress-core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +21 -0
  4. data/Rakefile +4 -0
  5. data/bin/waitress +22 -0
  6. data/ext/Thanks.md +1 -0
  7. data/ext/waitress_http11/ext_help.h +15 -0
  8. data/ext/waitress_http11/extconf.rb +6 -0
  9. data/ext/waitress_http11/http11.c +532 -0
  10. data/ext/waitress_http11/http11_parser.c +1216 -0
  11. data/ext/waitress_http11/http11_parser.h +49 -0
  12. data/ext/waitress_http11/http11_parser.java.rl +171 -0
  13. data/ext/waitress_http11/http11_parser.rl +165 -0
  14. data/ext/waitress_http11/http11_parser_common.rl +55 -0
  15. data/ext/waitress_http11/http11_wrb_parser.h +83 -0
  16. data/lib/waitress.rb +98 -0
  17. data/lib/waitress/chef.rb +110 -0
  18. data/lib/waitress/configure.rb +116 -0
  19. data/lib/waitress/handlers/dirhandler.rb +39 -0
  20. data/lib/waitress/handlers/handler.rb +57 -0
  21. data/lib/waitress/handlers/handler404.rb +25 -0
  22. data/lib/waitress/handlers/libhandler.rb +58 -0
  23. data/lib/waitress/kernel.rb +182 -0
  24. data/lib/waitress/parse/query.rb +60 -0
  25. data/lib/waitress/request.rb +45 -0
  26. data/lib/waitress/resources/default_config.rb +52 -0
  27. data/lib/waitress/resources/http/404.html +18 -0
  28. data/lib/waitress/resources/http/css/hack.css +37 -0
  29. data/lib/waitress/resources/http/css/waitress.css +57 -0
  30. data/lib/waitress/resources/http/fonts/eot/latin/hack-bold-latin-webfont.eot +0 -0
  31. data/lib/waitress/resources/http/fonts/eot/latin/hack-bolditalic-latin-webfont.eot +0 -0
  32. data/lib/waitress/resources/http/fonts/eot/latin/hack-italic-latin-webfont.eot +0 -0
  33. data/lib/waitress/resources/http/fonts/eot/latin/hack-regular-latin-webfont.eot +0 -0
  34. data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +241 -0
  35. data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +241 -0
  36. data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +241 -0
  37. data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +241 -0
  38. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bold-latin-webfont.ttf +0 -0
  39. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf +0 -0
  40. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-italic-latin-webfont.ttf +0 -0
  41. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-regular-latin-webfont.ttf +0 -0
  42. data/lib/waitress/resources/http/fonts/woff/latin/hack-bold-latin-webfont.woff +0 -0
  43. data/lib/waitress/resources/http/fonts/woff/latin/hack-bolditalic-latin-webfont.woff +0 -0
  44. data/lib/waitress/resources/http/fonts/woff/latin/hack-italic-latin-webfont.woff +0 -0
  45. data/lib/waitress/resources/http/fonts/woff/latin/hack-regular-latin-webfont.woff +0 -0
  46. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bold-latin-webfont.woff2 +0 -0
  47. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2 +0 -0
  48. data/lib/waitress/resources/http/fonts/woff2/latin/hack-italic-latin-webfont.woff2 +0 -0
  49. data/lib/waitress/resources/http/fonts/woff2/latin/hack-regular-latin-webfont.woff2 +0 -0
  50. data/lib/waitress/resources/http/img/404.png +0 -0
  51. data/lib/waitress/resources/http/index.html +15 -0
  52. data/lib/waitress/response.rb +104 -0
  53. data/lib/waitress/server.rb +115 -0
  54. data/lib/waitress/util.rb +713 -0
  55. data/lib/waitress/version.rb +3 -0
  56. data/lib/waitress/vhost.rb +217 -0
  57. data/lib/waitress_http11.so +0 -0
  58. data/waitress-core.gemspec +27 -0
  59. metadata +187 -0
@@ -0,0 +1,58 @@
1
+ module Waitress
2
+
3
+ # The LibraryHandler is used to handle requests to the VHost regarding the
4
+ # libraries to be loaded by other Handlers and .wrb files. This will take any
5
+ # requests to /libraries (or whatever the user has set it to) to load libraries
6
+ class LibraryHandler < Handler
7
+
8
+ attr_accessor :priority
9
+
10
+ def initialize libraries, libdir, liburi, vhost
11
+ @priority = 150
12
+ @vhost = vhost
13
+ @libraries, @libdir, @liburi = libraries, File.expand_path(libdir), liburi
14
+ FileUtils.mkdir_p(@libdir) unless File.exist?(@libdir)
15
+
16
+ @libraries.each do |name, lib|
17
+ l = {}
18
+ d = dirType(lib[:bindtype])
19
+ matches = Dir["#{d}/**/*.#{lib[:bindtype].to_s}"].select { |x| (x =~ lib[:pattern]) != nil }
20
+ if matches.length > 0
21
+ l[:file] = matches[0]
22
+ l[:type] = lib[:bindtype]
23
+ else
24
+ l = nil
25
+ end
26
+ @libraries[name] = l
27
+ end
28
+
29
+ [:css, :js].each do |k|
30
+ d = dirType k
31
+ FileUtils.mkdir_p(d) unless File.exist?(d)
32
+
33
+ Dir["#{d}/**/*.#{k.to_s}"].each do |fl|
34
+ @libraries[File.basename(fl).to_sym] = { :file => fl, :type => k }
35
+ end
36
+ end
37
+ end
38
+
39
+ def dirType k
40
+ File.join(@libdir, k.to_s)
41
+ end
42
+
43
+ def respond? request, vhost
44
+ path = request.path
45
+ return false unless path.start_with?("/#{@liburi}/")
46
+ name = path.sub("/#{@liburi}/", "").to_sym
47
+ @libraries.include?(name)
48
+ end
49
+
50
+ def serve request, response, client, vhost
51
+ path = request.path
52
+ name = path.sub("/#{@liburi}/", "").to_sym
53
+ lib = @libraries[name]
54
+ Waitress::Chef.serve_file request, response, client, vhost, lib[:file]
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,182 @@
1
+ # The Kernel Module provides global methods that will provide the 'builtins' for .wrb files
2
+ # and handlers. This is used to prevent verbose access of a namespace like Waitress::Global,
3
+ # and instead provide them here. Because requests are handled in new Processes, these values
4
+ # will change in each request and will not interfere.
5
+ module ::Kernel
6
+
7
+ # The +Waitress::Response+ object being used
8
+ def response_object
9
+ $RESPONSE
10
+ end
11
+
12
+ # The +Waitress::Request+ object being used
13
+ def request_object
14
+ $REQUEST
15
+ end
16
+
17
+ # Prepare the Kernel, by linking global variables
18
+ def kernel_prepare
19
+ $METHOD = get_method
20
+ $HEADERS = get_headers
21
+ $PATH = get_path
22
+ $URI = get_uri
23
+ $BODY = get_body
24
+ end
25
+
26
+ # Automatically load a library header into this file in the form of HTML.
27
+ # This will load a library in the VHost's libs/ folder, or any lib defined in the
28
+ # VHost's config.rb file with the name given. JS libraries will be linked with the
29
+ # <script> tag, whilst css files will be linked with the <link rel="stylesheet">
30
+ # tag. This is the recommended way of handling library loading.
31
+ # Params:
32
+ # +name+:: The name of the lib (the filename), or the name of the library as bound
33
+ # in the config.rb file.
34
+ def lib name
35
+ name = name.to_sym
36
+ type = $VHOST.libraries[name][:type]
37
+ libhome = $VHOST.liburi
38
+ if type == :js
39
+ echo "<script type='text/javascript' src='/#{libhome}/#{name}'></script>"
40
+ elsif type == :css
41
+ echo "<link rel='stylesheet' href='/#{libhome}/#{name}'></link>"
42
+ end
43
+ end
44
+
45
+ # Automatically load a Library Combo into this file. This will consecutively load
46
+ # all the libraries bound to the combination with the given name as defined in the
47
+ # VHost's config.rb file. This will call lib() for each of these libraries.
48
+ # Params:
49
+ # +name+:: The name of the combo to load
50
+ def combo name
51
+ name = name.to_sym
52
+ combo_arr = $VHOST.combos[name]
53
+ combo_arr.each { |n| lib(n) }
54
+ end
55
+
56
+ # Include another .wrb, .rb or any other file in the load path of the VHost into this
57
+ # file. If this file is .wrb or .rb, it will be evaluated. If it is another type of file
58
+ # (e.g. html), it will be directly echoed to the output buffer
59
+ # Params:
60
+ # +filename+:: The name of the file, relative to the loadpath
61
+ def includes filename
62
+ Waitress::Chef.include_file filename
63
+ end
64
+
65
+ # Include another .wrb, .rb or any other file in this file. If this file is
66
+ # .wrb or .rb, it will be evaluated. If it is another type of file
67
+ # (e.g. html), it will be directly echoed to the output buffer
68
+ # Params:
69
+ # +filename+:: The absolute filename of the file to load, anywhere in the filesystem
70
+ def includes_file filename
71
+ Waitress::Chef.include_absfile filename
72
+ end
73
+
74
+ # Returns a Hash of the GET query of the request. This may be an empty array
75
+ # if querystring was present
76
+ def get
77
+ request_object.get_query
78
+ end
79
+
80
+ # Returns a Hash of the POST query of the request. This may be an empty array
81
+ # if the body is not a valid querystring, or an exception raised if there was
82
+ # an error in parsing.
83
+ def post
84
+ request_object.post_query
85
+ end
86
+
87
+ # Get a header from the HTTP Request. This will fetch the header by the given
88
+ # name from the request object. Keep in mind that in requests, Headers are fully
89
+ # capitalized and any hyphens replaced with underscores (e.g. Content-Type becomes
90
+ # CONTENT_TYPE)
91
+ def get_header name
92
+ request_object.headers[name]
93
+ end
94
+
95
+ # Return the full list of headers available in the request object.
96
+ def get_headers
97
+ request_object.headers
98
+ end
99
+
100
+ # Returns the HTTP method that was used to retrieve this page (GET, POST, UPDATE,
101
+ # DELETE, PUT, etc)
102
+ def get_method
103
+ request_object.method
104
+ end
105
+
106
+ # Get the path of this request. This is after a URL rewrite, and does not contain
107
+ # a querystring. Be careful with these, as they start with a "/" and if not joined
108
+ # correctly can cause issues in the root of your filesystem (use File.join) if you
109
+ # plan to use this
110
+ def get_path
111
+ request_object.path
112
+ end
113
+
114
+ # Get the URI of this request. Unlike the path, the URI is not modified after a rewrite,
115
+ # and does contain a querystring. Use this if you want the *original* path and query
116
+ # of the request before it was rewritten
117
+ def get_uri
118
+ request_object.uri
119
+ end
120
+
121
+ # Get the request body. In most cases, this will be blank, but for POST requests it may
122
+ # contain a querystring, and for PUT and UPDATE methods it may contain other data
123
+ def get_body
124
+ request_object.body
125
+ end
126
+
127
+ # Get the querystring object as a string before it is parsed
128
+ def get_querystring
129
+ request_object.querystring
130
+ end
131
+
132
+ # Set a response header. This will be joined when writing the response with the delimiter ": "
133
+ # as in regular HTTP Protocol fashion.
134
+ # Params:
135
+ # +name+:: The name of the header, e.g. "Content-Type"
136
+ # +value+:: The value of the header, e.g. "text/html"
137
+ def set_header name, value
138
+ response_object.header name, value
139
+ end
140
+
141
+ # Set the content-type of the response. This is a shortcut to the Content-Type
142
+ # header and takes the full content-type (not fileextension) as an argument
143
+ # Params:
144
+ # +raw_type+:: The mime type of the content, e.g. "text/html"
145
+ def content_type raw_type
146
+ response_object.mime_raw raw_type
147
+ end
148
+
149
+ # Set the content-type of the response. This is a shortcut to the Content-Type
150
+ # header, and will also lookup the fileextension in the +Waitress::Util+ mime-type
151
+ # lookup.
152
+ # Params:
153
+ # +extension+:: The file extension to map to a mimetype, e.g. ".html"
154
+ def file_ext extension
155
+ response_object.mime extension
156
+ end
157
+
158
+ # Write a string to the output buffer. This will write directly to the body of the
159
+ # response, similar to what 'print()' does for STDOUT. Use this to write data to the
160
+ # output stream
161
+ def echo obj
162
+ str = obj.to_s
163
+ write str
164
+ end
165
+
166
+ # Write a string to the output buffer, followed by a newline. Similar to echo(),
167
+ # this will write to the output buffer, but also adds a "\n". This does to the
168
+ # client output as 'puts()' does to STDOUT. Use this to write data to the output
169
+ # stream
170
+ def println obj
171
+ echo(obj.to_s + "\n")
172
+ end
173
+
174
+ # Write a set of bytes directly to the output stream. Use this if you don't want
175
+ # to cast to a string as echo() and println() do.
176
+ def write bytes
177
+ r = response_object
178
+ r.body "" if r.body_io.nil?
179
+ r.body_io.write bytes
180
+ end
181
+
182
+ end
@@ -0,0 +1,60 @@
1
+ module Waitress
2
+ # A lot of this class uses methods from Rack::QueryParser in order to Parse
3
+ # a given QueryString into a Hash of key/value pairs
4
+ class QueryParser
5
+ require 'uri'
6
+
7
+ DEFAULT_SEP = /[&;] */n
8
+
9
+ # Unescape a HTTP URL to regular text. e.g. %20 becomes a space (" ")
10
+ def self.unescape str, enc=Encoding::UTF_8
11
+ URI.decode_www_form_component(str, enc)
12
+ end
13
+
14
+ # Parse the given QueryString into a hash of key/value pairs
15
+ def self.parse qs
16
+ return {} if qs.nil? || qs.empty?
17
+ results = {}
18
+ (qs || '').split(DEFAULT_SEP).each do |p|
19
+ k, v = p.split('='.freeze, 2).map! { |s| unescape(s) }
20
+
21
+ normalize results, k, v
22
+ end
23
+ results
24
+ end
25
+
26
+ def self.normalize hash, name, v
27
+ name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
28
+ k = $1 || ''
29
+ after = $' || ''
30
+
31
+ return if k.empty?
32
+
33
+ if after == ""
34
+ hash[k] = v
35
+ elsif after == "["
36
+ hash[name] = v
37
+ elsif after == "[]"
38
+ hash[k] ||= []
39
+ raise TypeError, "expected Array (got #{hash[k].class.name}) for param `#{k}'" unless hash[k].is_a?(Array)
40
+ hash[k] << v
41
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
42
+ child_key = $1
43
+ hash[k] ||= []
44
+ raise TypeError, "expected Array (got #{hash[k].class.name}) for param `#{k}'" unless hash[k].is_a?(Array)
45
+ if hash[k].last.is_a?(Hash) && !hash[k].last.key?(child_key)
46
+ normalize(hash[k].last, child_key, v)
47
+ else
48
+ hash[k] << normalize({}, child_key, v)
49
+ end
50
+ else
51
+ hash[k] ||= {}
52
+ raise TypeError, "expected Hash (got #{hash[k].class.name}) for param `#{k}'" unless hash[k].is_a?(Hash)
53
+ hash[k] = normalize_params(hash[k], after, v)
54
+ end
55
+
56
+ hash
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,45 @@
1
+ module Waitress
2
+ # The request class is used to represent a HTTP request by a client. This includes
3
+ # all the headers sent to the server by the client, request URI and those properties
4
+ # parsed by Mongrel, including the Path and QueryString. GET and POST queries are to
5
+ # be parsed on-request by the handler or .wrb file as to not waste CPU resources.
6
+ class Request
7
+
8
+ attr_accessor :method
9
+ attr_accessor :path
10
+ attr_accessor :uri
11
+ attr_accessor :querystring
12
+ attr_accessor :http_version
13
+ attr_accessor :body
14
+ attr_accessor :headers
15
+
16
+ def initialize method, path, uri, query, http_version, body, headers
17
+ @method = method
18
+ @path = Waitress::QueryParser.unescape(path)
19
+ @uri = Waitress::QueryParser.unescape(uri)
20
+ @querystring = query
21
+ @http_version = http_version
22
+ @body = body
23
+ @headers = headers
24
+ @marks = {}
25
+ end
26
+
27
+ # The GET query for the request in the form of a hash. This is parsed on-request
28
+ def get_query
29
+ @get ||= Waitress::QueryParser.parse(@querystring)
30
+ @get
31
+ end
32
+
33
+ # The POST query for the request in the form of a hash. This is parsed on-request
34
+ def post_query
35
+ @post ||= Waitress::QueryParser.parse(@body)
36
+ @post
37
+ end
38
+
39
+ def to_s
40
+ m = lambda { |a,x| x.nil? ? "" : "#{a}=#{x.inspect}" }
41
+ "#<#{self.class} method=#{@method} path=#{@path} #{m.call("query", @query)}>"
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,52 @@
1
+ # This is the configuration for your waitress server, accepting connections on port '2910'
2
+ Waitress.configure!(2910) do |w|
3
+
4
+ # You can run regular Ruby Code in here, too!
5
+ @home = "~/.waitress/www/"
6
+ def fl file
7
+ File.join(@home, file)
8
+ end
9
+
10
+ # This is your main Virtual Host, accepting connections to 'example.mysite.com'
11
+ w.host(/example.mysite.com/) do |host|
12
+ # This is where your public documents and pages are stored
13
+ host.root fl("example/http")
14
+
15
+ # This is where your non-public includes are stored
16
+ host.includes fl("example/rb")
17
+
18
+ # This will show up when a 404 error occurs
19
+ # host.set_404 fl("example/http/404.html")
20
+
21
+ # Want to rewrite a URL? No problem.
22
+ host.rewrite /some_url/, "some_other_url"
23
+ host.rewrite /capture_group_(\d)/, "capture/group\\1"
24
+
25
+ # Bind_Lib will allow you to automatically import lib tags into .wrb files
26
+ # Before they are sent to the client.
27
+ host.bind_lib /jquery.*/, :js, "jquery"
28
+ host.bind_lib /boostrap.*/, :css, "boots"
29
+
30
+ # Use combos to chain together libraries into a collection
31
+ host.combo "all-lib", "jquery", "boots"
32
+
33
+ # Change this to change where you store your libraries
34
+ host.libdir fl("libs")
35
+
36
+ # Change this to choose what URI the libraries are linked
37
+ # to (yoursite.com/libraries/library_name)
38
+ host.liburi "libraries"
39
+ end
40
+
41
+ # This is your other Virtual Host, accepting connections to any domain.
42
+ # The '0' represents the priority, with the default being 50. Higher priority
43
+ # Hosts will be chosen if the request matches multiple Hosts.
44
+ w.host(/.*/, 0) do |host|
45
+ # This is where your public documents and pages are stored
46
+ host.root fl("main/http")
47
+
48
+ # This is where your non-public includes are stored
49
+ host.includes fl("main/rb")
50
+ end
51
+
52
+ end
@@ -0,0 +1,18 @@
1
+ <html>
2
+ <head>
3
+ <title> 404 - Page Not Found </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="textcontainer">
10
+ <h1> 404 </h1>
11
+ <h2> You ordered something that wasn't on the menu </h2>
12
+ </div>
13
+ <div class="imgcontainer">
14
+ <img src="/img/404.png">
15
+ </div>
16
+ </div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,37 @@
1
+ /*!
2
+ * Hack v2.013 - https://sourcefoundry.org/hack/
3
+ * Licenses - Fonts: Hack Open Font License + Bitstream Vera license, CSS: MIT License
4
+ */
5
+ /* FONT PATHS
6
+ * -------------------------- */
7
+ @font-face {
8
+ font-family: 'Hack';
9
+ src: url('../fonts/eot/latin/hack-regular-latin-webfont.eot?v=2.013');
10
+ src: url('../fonts/eot/latin/hack-regular-latin-webfont.eot?#iefix&v=2.013') format('embedded-opentype'), url('../fonts/woff2/latin/hack-regular-latin-webfont.woff2?v=2.013') format('woff2'), url('../fonts/woff/latin/hack-regular-latin-webfont.woff?v=2.013') format('woff'), url('../fonts/web-ttf/latin/hack-regular-latin-webfont.ttf?v=2.013') format('truetype'), url('../fonts/svg/latin/hack-regular-latin-webfont.svg?v=2.013#hackregular') format('svg');
11
+ font-weight: 400;
12
+ font-style: normal;
13
+ }
14
+
15
+ @font-face {
16
+ font-family: 'Hack';
17
+ src: url('../fonts/eot/latin/hack-bold-latin-webfont.eot?v=2.013');
18
+ src: url('../fonts/eot/latin/hack-bold-latin-webfont.eot?#iefix&v=2.013') format('embedded-opentype'), url('../fonts/woff2/latin/hack-bold-latin-webfont.woff2?v=2.013') format('woff2'), url('../fonts/woff/latin/hack-bold-latin-webfont.woff?v=2.013') format('woff'), url('../fonts/web-ttf/latin/hack-bold-latin-webfont.ttf?v=2.013') format('truetype'), url('../fonts/svg/latin/hack-bold-latin-webfont.svg?v=2.013#hackbold') format('svg');
19
+ font-weight: 700;
20
+ font-style: normal;
21
+ }
22
+
23
+ @font-face {
24
+ font-family: 'Hack';
25
+ src: url('../fonts/eot/latin/hack-italic-latin-webfont.eot?v=2.013');
26
+ src: url('../fonts/eot/latin/hack-italic-latin-webfont.eot?#iefix&v=2.013') format('embedded-opentype'), url('../fonts/woff2/latin/hack-italic-latin-webfont.woff2?v=2.013') format('woff2'), url('../fonts/woff/latin/hack-italic-latin-webfont.woff?v=2.013') format('woff'), url('../fonts/web-ttf/latin/hack-italic-latin-webfont.ttf?v=2.013') format('truetype'), url('../fonts/svg/latin/hack-italic-latin-webfont.svg?v=2.013#hackitalic') format('svg');
27
+ font-weight: 400;
28
+ font-style: italic;
29
+ }
30
+
31
+ @font-face {
32
+ font-family: 'Hack';
33
+ src: url('../fonts/eot/latin/hack-bolditalic-latin-webfont.eot?v=2.013');
34
+ src: url('../fonts/eot/latin/hack-bolditalic-latin-webfont.eot?#iefix&v=2.013') format('embedded-opentype'), url('../fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2?v=2.013') format('woff2'), url('../fonts/woff/latin/hack-bolditalic-latin-webfont.woff?v=2.013') format('woff'), url('../fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf?v=2.013') format('truetype'), url('../fonts/svg/latin/hack-bolditalic-latin-webfont.svg?v=2.013#hackbolditalic') format('svg');
35
+ font-weight: 700;
36
+ font-style: italic;
37
+ }