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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/LICENSE +21 -21
  4. data/Rakefile +13 -4
  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 +83 -83
  16. data/lib/waitress/chef.rb +110 -110
  17. data/lib/waitress/configure.rb +116 -116
  18. data/lib/waitress/handlers/dirhandler.rb +39 -39
  19. data/lib/waitress/handlers/handler.rb +57 -57
  20. data/lib/waitress/handlers/handler404.rb +25 -25
  21. data/lib/waitress/handlers/libhandler.rb +58 -58
  22. data/lib/waitress/kernel.rb +182 -182
  23. data/lib/waitress/parse/query.rb +60 -60
  24. data/lib/waitress/request.rb +45 -45
  25. data/lib/waitress/resources/default_config.rb +52 -52
  26. data/lib/waitress/resources/http/404.html +18 -18
  27. data/lib/waitress/resources/http/css/hack.css +37 -37
  28. data/lib/waitress/resources/http/css/waitress.css +57 -57
  29. data/lib/waitress/resources/http/fonts/eot/latin/hack-bold-latin-webfont.eot +0 -0
  30. data/lib/waitress/resources/http/fonts/eot/latin/hack-bolditalic-latin-webfont.eot +0 -0
  31. data/lib/waitress/resources/http/fonts/eot/latin/hack-italic-latin-webfont.eot +0 -0
  32. data/lib/waitress/resources/http/fonts/eot/latin/hack-regular-latin-webfont.eot +0 -0
  33. data/lib/waitress/resources/http/fonts/svg/latin/hack-bold-latin-webfont.svg +240 -240
  34. data/lib/waitress/resources/http/fonts/svg/latin/hack-bolditalic-latin-webfont.svg +240 -240
  35. data/lib/waitress/resources/http/fonts/svg/latin/hack-italic-latin-webfont.svg +240 -240
  36. data/lib/waitress/resources/http/fonts/svg/latin/hack-regular-latin-webfont.svg +240 -240
  37. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bold-latin-webfont.ttf +0 -0
  38. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-bolditalic-latin-webfont.ttf +0 -0
  39. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-italic-latin-webfont.ttf +0 -0
  40. data/lib/waitress/resources/http/fonts/web-ttf/latin/hack-regular-latin-webfont.ttf +0 -0
  41. data/lib/waitress/resources/http/fonts/woff/latin/hack-bold-latin-webfont.woff +0 -0
  42. data/lib/waitress/resources/http/fonts/woff/latin/hack-bolditalic-latin-webfont.woff +0 -0
  43. data/lib/waitress/resources/http/fonts/woff/latin/hack-italic-latin-webfont.woff +0 -0
  44. data/lib/waitress/resources/http/fonts/woff/latin/hack-regular-latin-webfont.woff +0 -0
  45. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bold-latin-webfont.woff2 +0 -0
  46. data/lib/waitress/resources/http/fonts/woff2/latin/hack-bolditalic-latin-webfont.woff2 +0 -0
  47. data/lib/waitress/resources/http/fonts/woff2/latin/hack-italic-latin-webfont.woff2 +0 -0
  48. data/lib/waitress/resources/http/fonts/woff2/latin/hack-regular-latin-webfont.woff2 +0 -0
  49. data/lib/waitress/resources/http/img/404.png +0 -0
  50. data/lib/waitress/resources/http/index.html +15 -15
  51. data/lib/waitress/response.rb +104 -104
  52. data/lib/waitress/server.rb +126 -115
  53. data/lib/waitress/util.rb +707 -713
  54. data/lib/waitress/version.rb +3 -3
  55. data/lib/waitress/vhost.rb +217 -217
  56. data/lib/waitress.rb +98 -98
  57. data/lib/waitress_http11.bundle +0 -0
  58. data/waitress-core.gemspec +29 -27
  59. metadata +35 -7
  60. data/lib/waitress_http11.so +0 -0
@@ -1,25 +1,25 @@
1
- module Waitress
2
-
3
- # The 404 Handler is a simple "Catch-All" handler which will be triggered if
4
- # a valid handler is not found for the page, and will show an error page
5
- # telling the user the page cannot be found
6
- class Handler404 < ErrorHandler
7
-
8
- def serve request, response, client, vhost
9
- response.status 404
10
- e404page = vhost.get_404
11
- if !e404page.nil? && (Waitress::Chef.find_file(e404page)[:result]==:ok)
12
- Waitress::Chef.serve_file request, response, client, vhost, e404page
13
- else
14
- if vhost.resources?
15
- h = File.join Waitress::Chef.resources_http, "404.html"
16
- Waitress::Chef.serve_file request, response, client, vhost, h
17
- else
18
- response.mime ".html"
19
- response.body "<h1> 404 - Not Found </h1> <p> The page you have requested is not here </p>"
20
- end
21
- end
22
- end
23
-
24
- end
25
- end
1
+ module Waitress
2
+
3
+ # The 404 Handler is a simple "Catch-All" handler which will be triggered if
4
+ # a valid handler is not found for the page, and will show an error page
5
+ # telling the user the page cannot be found
6
+ class Handler404 < ErrorHandler
7
+
8
+ def serve request, response, client, vhost
9
+ response.status 404
10
+ e404page = vhost.get_404
11
+ if !e404page.nil? && (Waitress::Chef.find_file(e404page)[:result]==:ok)
12
+ Waitress::Chef.serve_file request, response, client, vhost, e404page
13
+ else
14
+ if vhost.resources?
15
+ h = File.join Waitress::Chef.resources_http, "404.html"
16
+ Waitress::Chef.serve_file request, response, client, vhost, h
17
+ else
18
+ response.mime ".html"
19
+ response.body "<h1> 404 - Not Found </h1> <p> The page you have requested is not here </p>"
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -1,58 +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
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
@@ -1,182 +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
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 set_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
@@ -1,60 +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
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(hash[k], after, v)
54
+ end
55
+
56
+ hash
57
+ end
58
+
59
+ end
60
+ end