plezi 0.7.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/CHANGELOG.md +450 -0
- data/Gemfile +4 -0
- data/KNOWN_ISSUES.md +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +341 -0
- data/Rakefile +2 -0
- data/TODO.md +19 -0
- data/bin/plezi +301 -0
- data/lib/plezi.rb +125 -0
- data/lib/plezi/base/cache.rb +77 -0
- data/lib/plezi/base/connections.rb +33 -0
- data/lib/plezi/base/dsl.rb +177 -0
- data/lib/plezi/base/engine.rb +85 -0
- data/lib/plezi/base/events.rb +84 -0
- data/lib/plezi/base/io_reactor.rb +41 -0
- data/lib/plezi/base/logging.rb +62 -0
- data/lib/plezi/base/rack_app.rb +89 -0
- data/lib/plezi/base/services.rb +57 -0
- data/lib/plezi/base/timers.rb +71 -0
- data/lib/plezi/handlers/controller_magic.rb +383 -0
- data/lib/plezi/handlers/http_echo.rb +27 -0
- data/lib/plezi/handlers/http_host.rb +215 -0
- data/lib/plezi/handlers/http_router.rb +69 -0
- data/lib/plezi/handlers/magic_helpers.rb +43 -0
- data/lib/plezi/handlers/route.rb +272 -0
- data/lib/plezi/handlers/stubs.rb +143 -0
- data/lib/plezi/server/README.md +33 -0
- data/lib/plezi/server/helpers/http.rb +169 -0
- data/lib/plezi/server/helpers/mime_types.rb +999 -0
- data/lib/plezi/server/protocols/http_protocol.rb +318 -0
- data/lib/plezi/server/protocols/http_request.rb +133 -0
- data/lib/plezi/server/protocols/http_response.rb +294 -0
- data/lib/plezi/server/protocols/websocket.rb +208 -0
- data/lib/plezi/server/protocols/ws_response.rb +92 -0
- data/lib/plezi/server/services/basic_service.rb +224 -0
- data/lib/plezi/server/services/no_service.rb +196 -0
- data/lib/plezi/server/services/ssl_service.rb +193 -0
- data/lib/plezi/version.rb +3 -0
- data/plezi.gemspec +26 -0
- data/resources/404.erb +68 -0
- data/resources/404.haml +64 -0
- data/resources/404.html +67 -0
- data/resources/404.slim +63 -0
- data/resources/500.erb +68 -0
- data/resources/500.haml +63 -0
- data/resources/500.html +67 -0
- data/resources/500.slim +63 -0
- data/resources/Gemfile +85 -0
- data/resources/anorexic_gray.png +0 -0
- data/resources/anorexic_websockets.html +47 -0
- data/resources/code.rb +8 -0
- data/resources/config.ru +39 -0
- data/resources/controller.rb +139 -0
- data/resources/db_ac_config.rb +58 -0
- data/resources/db_dm_config.rb +51 -0
- data/resources/db_sequel_config.rb +42 -0
- data/resources/en.yml +204 -0
- data/resources/environment.rb +41 -0
- data/resources/haml_config.rb +6 -0
- data/resources/i18n_config.rb +14 -0
- data/resources/rakefile.rb +22 -0
- data/resources/redis_config.rb +35 -0
- data/resources/routes.rb +26 -0
- data/resources/welcome_page.html +72 -0
- data/websocket chatroom.md +639 -0
- metadata +141 -0
@@ -0,0 +1,318 @@
|
|
1
|
+
module Plezi
|
2
|
+
|
3
|
+
# this module is the protocol (controller) for the HTTP server.
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# to do: implemet logging, support body types: multipart (non-ASCII form data / uploaded files), json & xml
|
7
|
+
class HTTPProtocol
|
8
|
+
|
9
|
+
HTTP_METHODS = %w{GET HEAD POST PUT DELETE TRACE OPTIONS}
|
10
|
+
|
11
|
+
attr_accessor :service
|
12
|
+
|
13
|
+
def initialize service, params
|
14
|
+
@service = service
|
15
|
+
@parser_stage = 0
|
16
|
+
@parser_data = {}
|
17
|
+
@parser_body = ''
|
18
|
+
@parser_chunk = ''
|
19
|
+
@parser_length = 0
|
20
|
+
@locker = Mutex.new
|
21
|
+
@@rack_dictionary ||= {"HOST".freeze => :host_name, 'REQUEST_METHOD'.freeze => :method,
|
22
|
+
'PATH_INFO'.freeze => :path, 'QUERY_STRING'.freeze => :query,
|
23
|
+
'SERVER_NAME'.freeze => :host_name, 'SERVER_PORT'.freeze => :port,
|
24
|
+
'rack.url_scheme'.freeze => :requested_protocol}
|
25
|
+
end
|
26
|
+
|
27
|
+
# called when connection is initialized.
|
28
|
+
def on_connect service
|
29
|
+
end
|
30
|
+
|
31
|
+
# called when data is recieved.
|
32
|
+
#
|
33
|
+
# this method is called within a lock on the service (Mutex) - craeful from double locking.
|
34
|
+
#
|
35
|
+
# typically returns an Array with any data not yet processed (to be returned to the in-que)... but here it always processes (or discards) the data.
|
36
|
+
def on_message(service)
|
37
|
+
# parse the request
|
38
|
+
@locker.synchronize { parse_message }
|
39
|
+
if (@parser_stage == 1) && @parser_data[:version] >= 1.1
|
40
|
+
# send 100 continue message????? doesn't work! both Crome and Safari go crazy if this is sent after the request was sent (but before all the packets were recieved... msgs over 1 Mb).
|
41
|
+
# Plezi.push_event Proc.new { Plezi.info "sending continue signal."; service.send_nonblock "100 Continue\r\n\r\n" }
|
42
|
+
# service.send_unsafe_interrupt "100 Continue\r\n\r\n" # causes double lock on service
|
43
|
+
end
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# # called when a disconnect is fired
|
48
|
+
# # (socket was disconnected / service should be disconnected / shutdown / socket error)
|
49
|
+
def on_disconnect service
|
50
|
+
end
|
51
|
+
|
52
|
+
# called when an exception was raised
|
53
|
+
# (socket was disconnected / service should be disconnected / shutdown / socket error)
|
54
|
+
def on_exception service, e
|
55
|
+
Plezi.error e
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Protocol specific helper methods.
|
60
|
+
|
61
|
+
# parses incoming data
|
62
|
+
def parse_message data = nil
|
63
|
+
data ||= service.read.to_s.lines.to_a
|
64
|
+
# require 'pry'; binding.pry
|
65
|
+
if @parser_stage == 0
|
66
|
+
return false unless parse_method data
|
67
|
+
end
|
68
|
+
if @parser_stage == 1
|
69
|
+
return false unless parse_head data
|
70
|
+
end
|
71
|
+
if @parser_stage == 2
|
72
|
+
return false unless parse_body data
|
73
|
+
end
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
# parses the method request (the first line in the HTTP request).
|
78
|
+
def parse_method data
|
79
|
+
return false unless data[0] && data[0].match(/^#{HTTP_METHODS.join('|')}/)
|
80
|
+
@parser_data[:time_recieved] = Time.now
|
81
|
+
@parser_data[:params] = {}
|
82
|
+
@parser_data[:cookies] = Cookies.new
|
83
|
+
@parser_data[:method] = ''
|
84
|
+
@parser_data[:query] = ''
|
85
|
+
@parser_data[:original_path] = ''
|
86
|
+
@parser_data[:path] = ''
|
87
|
+
if defined? Rack
|
88
|
+
@parser_data['rack.version'] = Rack::VERSION
|
89
|
+
@parser_data['rack.multithread'] = true
|
90
|
+
@parser_data['rack.multiprocess'] = false
|
91
|
+
@parser_data['rack.hijack?'] = false
|
92
|
+
@parser_data['rack.logger'] = Plezi.logger
|
93
|
+
end
|
94
|
+
@parser_data[:method], @parser_data[:query], @parser_data[:version] = data.shift.split(/[\s]+/)
|
95
|
+
@parser_data[:version] = (@parser_data[:version] || 'HTTP/1.1').match(/[0-9\.]+/).to_s.to_f
|
96
|
+
data.shift while data[0].to_s.match /^[\r\n]+/
|
97
|
+
@parser_stage = 1
|
98
|
+
end
|
99
|
+
|
100
|
+
#parses the head on a request (headers and values).
|
101
|
+
def parse_head data
|
102
|
+
until data[0].nil? || data[0].match(/^[\r\n]+$/)
|
103
|
+
m = data.shift.match(/^([^:]*):[\s]*([^\r\n]*)/)
|
104
|
+
# move cookies to cookie-jar, all else goes to headers
|
105
|
+
case m[1].downcase
|
106
|
+
when 'cookie'
|
107
|
+
HTTP.extract_data m[2].split(/[;,][\s]?/), @parser_data[:cookies], :uri
|
108
|
+
end
|
109
|
+
@parser_data[ HTTP.make_utf8!(m[1]).downcase ] ? (@parser_data[ HTTP.make_utf8!(m[1]).downcase ] << ", #{HTTP.make_utf8! m[2]}"): (@parser_data[ HTTP.make_utf8!(m[1]).downcase ] = HTTP.make_utf8! m[2])
|
110
|
+
end
|
111
|
+
return false unless data[0]
|
112
|
+
data.shift while data[0] && data[0].match(/^[\r\n]+$/)
|
113
|
+
if @parser_data["transfer-coding"] || (@parser_data["content-length"] && @parser_data["content-length"].to_i != 0) || @parser_data["content-type"]
|
114
|
+
@parser_stage = 2
|
115
|
+
else
|
116
|
+
# create request object and hand over to handler
|
117
|
+
complete_request
|
118
|
+
return parse_message data unless data.empty?
|
119
|
+
end
|
120
|
+
true
|
121
|
+
end
|
122
|
+
|
123
|
+
#parses the body of a request.
|
124
|
+
def parse_body data
|
125
|
+
# check for body is needed, if exists and if complete
|
126
|
+
if @parser_data["transfer-coding"] == "chunked"
|
127
|
+
until data.empty? || data[0].to_s.match(/0(\r)?\n/)
|
128
|
+
if @parser_length == 0
|
129
|
+
@parser_length = data.to_s.shift.match(/^[a-z0-9A-Z]+/).to_i(16)
|
130
|
+
@parser_chunk.clear
|
131
|
+
end
|
132
|
+
unless @parser_length == 0
|
133
|
+
@parser_chunk << data.shift while ( (@parser_length >= @parser_chunk.bytesize) && data[0])
|
134
|
+
end
|
135
|
+
if @parser_length <= @parser_chunk.bytesize
|
136
|
+
@parser_body << @parser_chunk.byteslice(0, @parser_body.bytesize)
|
137
|
+
@parser_length = 0
|
138
|
+
@parser_chunk.clear
|
139
|
+
end
|
140
|
+
end
|
141
|
+
return false unless data[0].to_s.match(/0(\r)?\n/)
|
142
|
+
true until data.empty? || data.shift.match(/^[\r\n]+$/)
|
143
|
+
data.shift while data[0].to_s.match /^[\r\n]+$/
|
144
|
+
elsif @parser_data["content-length"].to_i
|
145
|
+
@parser_length = @parser_data["content-length"].to_i if @parser_length == 0
|
146
|
+
@parser_chunk << data.shift while @parser_length > @parser_chunk.bytesize && data[0]
|
147
|
+
return false if @parser_length > @parser_chunk.bytesize
|
148
|
+
@parser_body = @parser_chunk.byteslice(0, @parser_length)
|
149
|
+
@parser_chunk.clear
|
150
|
+
else
|
151
|
+
Plezi.warn 'bad body request - trying to read'
|
152
|
+
@parser_body << data.shift while data[0] && !data[0].match(/^[\r\n]+$/)
|
153
|
+
end
|
154
|
+
# parse body (POST parameters)
|
155
|
+
read_body
|
156
|
+
|
157
|
+
# complete request
|
158
|
+
complete_request
|
159
|
+
|
160
|
+
#read next request unless data is finished
|
161
|
+
return parse_message data unless data.empty?
|
162
|
+
true
|
163
|
+
end
|
164
|
+
|
165
|
+
# completes the parsing of the request and sends the request to the handler.
|
166
|
+
def complete_request
|
167
|
+
#finalize params and query properties
|
168
|
+
m = @parser_data[:query].match /(([a-z0-9A-Z]+):\/\/)?(([^\/\:]+))?(:([0-9]+))?([^\?\#]*)(\?([^\#]*))?/
|
169
|
+
@parser_data[:requested_protocol] = m[1] || (service.ssl? ? 'https' : 'http')
|
170
|
+
@parser_data[:host_name] = m[4] || (@parser_data['host'] ? @parser_data['host'].match(/^[^:]*/).to_s : nil)
|
171
|
+
@parser_data[:port] = m[6] || (@parser_data['host'] ? @parser_data['host'].match(/:([0-9]*)/).to_a[1] : nil)
|
172
|
+
@parser_data[:original_path] = HTTP.decode(m[7], :uri) || '/'
|
173
|
+
@parser_data['host'] ||= "#{@parser_data[:host_name]}:#{@parser_data[:port]}"
|
174
|
+
# parse query for params - m[9] is the data part of the query
|
175
|
+
if m[9]
|
176
|
+
HTTP.extract_data m[9].split(/[&;]/), @parser_data[:params]
|
177
|
+
end
|
178
|
+
|
179
|
+
HTTP.make_utf8! @parser_data[:original_path]
|
180
|
+
@parser_data[:path] = @parser_data[:original_path].chomp('/')
|
181
|
+
@parser_data[:original_path].freeze
|
182
|
+
|
183
|
+
HTTP.make_utf8! @parser_data[:host_name] if @parser_data[:host_name]
|
184
|
+
HTTP.make_utf8! @parser_data[:query]
|
185
|
+
|
186
|
+
@parser_data[:client_ip] = @parser_data['x-forwarded-for'].to_s.split(/,[\s]?/)[0] || (service.socket.remote_address.ip_address) rescue 'unknown IP'
|
187
|
+
|
188
|
+
@@rack_dictionary.each {|k,v| @parser_data[k] = @parser_data[v]}
|
189
|
+
|
190
|
+
#create request
|
191
|
+
request = HTTPRequest.new service
|
192
|
+
request.update @parser_data
|
193
|
+
|
194
|
+
#clear current state
|
195
|
+
@parser_data.clear
|
196
|
+
@parser_body.clear
|
197
|
+
@parser_chunk.clear
|
198
|
+
@parser_length = 0
|
199
|
+
@parser_stage = 0
|
200
|
+
|
201
|
+
#check for server-responses
|
202
|
+
case request.request_method
|
203
|
+
when "TRACE"
|
204
|
+
return true
|
205
|
+
when "OPTIONS"
|
206
|
+
Plezi.push_event Proc.new do
|
207
|
+
response = HTTPResponse.new request
|
208
|
+
response[:Allow] = "GET,HEAD,POST,PUT,DELETE,OPTIONS"
|
209
|
+
response["access-control-allow-origin"] = "*"
|
210
|
+
response['content-length'] = 0
|
211
|
+
response.finish
|
212
|
+
end
|
213
|
+
return true
|
214
|
+
end
|
215
|
+
|
216
|
+
#pass it to the handler or decler error.
|
217
|
+
if service && service.handler
|
218
|
+
Plezi.callback service.handler, :on_request, request
|
219
|
+
else
|
220
|
+
Plezi.error "No Handler for this HTTP service."
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# read the body's data and parse any incoming data.
|
225
|
+
def read_body
|
226
|
+
# parse content
|
227
|
+
case @parser_data["content-type"].to_s
|
228
|
+
when /x-www-form-urlencoded/
|
229
|
+
HTTP.extract_data @parser_body.split(/[&;]/), @parser_data[:params], :uri
|
230
|
+
when /multipart\/form-data/
|
231
|
+
read_multipart @parser_data, @parser_body
|
232
|
+
when /text\/xml/
|
233
|
+
# to-do support xml? support json?
|
234
|
+
@parser_data[:body] = @parser_body.dup
|
235
|
+
when /application\/json/
|
236
|
+
@parser_data[:body] = @parser_body.dup
|
237
|
+
JSON.parse(HTTP.make_utf8! @parser_data[:body]).each {|k, v| HTTP.add_param_to_hash k, v, @parser_data[:params]}
|
238
|
+
else
|
239
|
+
@parser_data[:body] = @parser_body.dup
|
240
|
+
Plezi.error "POST body type (#{@parser_data["content-type"]}) cannot be parsed. raw body is kept in the request's data as request[:body]: #{@parser_body}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# parse a mime/multipart body or part.
|
245
|
+
def read_multipart headers, part, name_prefix = ''
|
246
|
+
if headers["content-type"].to_s.match /multipart/
|
247
|
+
boundry = headers["content-type"].match(/boundary=([^\s]+)/)[1]
|
248
|
+
if headers["content-disposition"].to_s.match /name=/
|
249
|
+
if name_prefix.empty?
|
250
|
+
name_prefix << HTTP.decode(headers["content-disposition"].to_s.match(/name="([^"]*)"/)[1])
|
251
|
+
else
|
252
|
+
name_prefix << "[#{HTTP.decode(headers["content-disposition"].to_s.match(/name="([^"]*)"/)[1])}]"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
part.split(/([\r]?\n)?--#{boundry}(--)?[\r]?\n/).each do |p|
|
256
|
+
unless p.strip.empty? || p=='--'
|
257
|
+
# read headers
|
258
|
+
h = {}
|
259
|
+
p = p.lines
|
260
|
+
while p[0].match(/^[^:]+:[^\r\n]+/)
|
261
|
+
m = p.shift.match(/^([^:]+):[\s]?([^\r\n]+)/)
|
262
|
+
h[m[1].downcase] = m[2]
|
263
|
+
end
|
264
|
+
if p[0].strip.empty?
|
265
|
+
p.shift
|
266
|
+
else
|
267
|
+
Plezi.error 'Expected empty line after last header - empty line missing.'
|
268
|
+
end
|
269
|
+
# send headers and body to be read
|
270
|
+
read_multipart h, p.join, name_prefix
|
271
|
+
end
|
272
|
+
end
|
273
|
+
return
|
274
|
+
end
|
275
|
+
|
276
|
+
# require a part body to exist (data exists) for parsing
|
277
|
+
return true if part.to_s.empty?
|
278
|
+
|
279
|
+
# convert part to `charset` if charset is defined?
|
280
|
+
|
281
|
+
if !headers["content-disposition"]
|
282
|
+
Plezi.error "Wrong multipart format with headers: #{headers} and body: #{part}"
|
283
|
+
return
|
284
|
+
end
|
285
|
+
|
286
|
+
cd = {}
|
287
|
+
|
288
|
+
HTTP.extract_data headers["content-disposition"].match(/[^;];([^\r\n]*)/)[1].split(/[;,][\s]?/), cd, :uri
|
289
|
+
|
290
|
+
name = name_prefix.dup
|
291
|
+
|
292
|
+
if name_prefix.empty?
|
293
|
+
name << HTTP.decode(cd[:name][1..-2])
|
294
|
+
else
|
295
|
+
name << "[#{HTTP.decode(cd[:name][1..-2])}]"
|
296
|
+
end
|
297
|
+
if headers["content-type"]
|
298
|
+
HTTP.add_param_to_hash "#{name}[data]", part, @parser_data[:params]
|
299
|
+
HTTP.add_param_to_hash "#{name}[type]", HTTP.make_utf8!(headers["content-type"]), @parser_data[:params]
|
300
|
+
cd.each {|k,v| HTTP.add_param_to_hash "#{name}[#{k.to_s}]", HTTP.make_utf8!(v[1..-2]), @parser_data[:params] unless k == :name}
|
301
|
+
else
|
302
|
+
HTTP.add_param_to_hash name, HTTP.decode(part, :utf8), @parser_data[:params]
|
303
|
+
end
|
304
|
+
true
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
## Heroku/extra headers info
|
310
|
+
|
311
|
+
# All headers are considered to be case-insensitive, as per HTTP Specification.
|
312
|
+
# X-Forwarded-For: the originating IP address of the client connecting to the Heroku router
|
313
|
+
# X-Forwarded-Proto: the originating protocol of the HTTP request (example: https)
|
314
|
+
# X-Forwarded-Port: the originating port of the HTTP request (example: 443)
|
315
|
+
# X-Request-Start: unix timestamp (milliseconds) when the request was received by the router
|
316
|
+
# X-Request-Id: the Heroku HTTP Request ID
|
317
|
+
# Via: a code name for the Heroku router
|
318
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Plezi
|
2
|
+
|
3
|
+
# class is the base for the HTTP server.
|
4
|
+
#
|
5
|
+
# the class is initialized with a TCP/IP connection socket and starts
|
6
|
+
# an event driven cycle using the `EventStack.push` and `EventStack.reverse_async`.
|
7
|
+
#
|
8
|
+
# to-do: fox logging.
|
9
|
+
class HTTPRequest < Hash
|
10
|
+
|
11
|
+
def initialize service
|
12
|
+
super()
|
13
|
+
self[:plezi_service] = service
|
14
|
+
end
|
15
|
+
|
16
|
+
public
|
17
|
+
|
18
|
+
# the request's headers
|
19
|
+
def headers
|
20
|
+
self.select {|k,v| k.is_a? String }
|
21
|
+
end
|
22
|
+
# the request's method (GET, POST... etc').
|
23
|
+
def request_method
|
24
|
+
self[:method]
|
25
|
+
end
|
26
|
+
# set request's method (GET, POST... etc').
|
27
|
+
def request_method= value
|
28
|
+
self[:method] = value
|
29
|
+
end
|
30
|
+
# the parameters sent by the client.
|
31
|
+
def params
|
32
|
+
self[:params]
|
33
|
+
end
|
34
|
+
# the cookies sent by the client.
|
35
|
+
def cookies
|
36
|
+
self[:cookies]
|
37
|
+
end
|
38
|
+
|
39
|
+
# the query string
|
40
|
+
def query
|
41
|
+
self[:query]
|
42
|
+
end
|
43
|
+
|
44
|
+
# the original (frozen) path (resource requested).
|
45
|
+
def original_path
|
46
|
+
self[:original_path]
|
47
|
+
end
|
48
|
+
|
49
|
+
# the requested path (rewritable).
|
50
|
+
def path
|
51
|
+
self[:path]
|
52
|
+
end
|
53
|
+
def path=(new_path)
|
54
|
+
self[:path] = new_path
|
55
|
+
end
|
56
|
+
|
57
|
+
# the base url ([http/https]://host[:port])
|
58
|
+
def base_url switch_protocol = nil
|
59
|
+
"#{switch_protocol || self[:requested_protocol]}://#{self[:host_name]}#{self[:port]? ":#{self[:port]}" : ''}"
|
60
|
+
end
|
61
|
+
|
62
|
+
# the service (socket wrapper) that answered this request
|
63
|
+
def service
|
64
|
+
self[:plezi_service]
|
65
|
+
end
|
66
|
+
# the protocol managing this request
|
67
|
+
def protocol
|
68
|
+
self[:requested_protocol]
|
69
|
+
end
|
70
|
+
# the handler dealing with this request
|
71
|
+
def handler
|
72
|
+
self[:plezi_service].handler
|
73
|
+
end
|
74
|
+
|
75
|
+
# method recognition
|
76
|
+
|
77
|
+
# returns true of the method == GET
|
78
|
+
def get?
|
79
|
+
self[:method] == 'GET'
|
80
|
+
end
|
81
|
+
# returns true of the method == HEAD
|
82
|
+
def head?
|
83
|
+
self[:method] == 'HEAD'
|
84
|
+
end
|
85
|
+
# returns true of the method == POST
|
86
|
+
def post?
|
87
|
+
self[:method] == 'POST'
|
88
|
+
end
|
89
|
+
# returns true of the method == PUT
|
90
|
+
def put?
|
91
|
+
self[:method] == 'PUT'
|
92
|
+
end
|
93
|
+
# returns true of the method == DELETE
|
94
|
+
def delete?
|
95
|
+
self[:method] == 'DELETE'
|
96
|
+
end
|
97
|
+
# returns true of the method == TRACE
|
98
|
+
def trace?
|
99
|
+
self[:method] == 'TRACE'
|
100
|
+
end
|
101
|
+
# returns true of the method == OPTIONS
|
102
|
+
def options?
|
103
|
+
self[:method] == 'OPTIONS'
|
104
|
+
end
|
105
|
+
# returns true of the method == CONNECT
|
106
|
+
def connect?
|
107
|
+
self[:method] == 'CONNECT'
|
108
|
+
end
|
109
|
+
# returns true of the method == PATCH
|
110
|
+
def patch?
|
111
|
+
self[:method] == 'PATCH'
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
######
|
119
|
+
## example requests
|
120
|
+
|
121
|
+
# GET / HTTP/1.1
|
122
|
+
# Host: localhost:2000
|
123
|
+
# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
124
|
+
# Cookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w
|
125
|
+
# User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25
|
126
|
+
# Accept-Language: en-us
|
127
|
+
# Accept-Encoding: gzip, deflate
|
128
|
+
# Connection: keep-alive
|
129
|
+
#
|
130
|
+
# => "GET / HTTP/1.1\n\rHost: localhost:2000\n\rAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n\rCookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\n\rUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\n\rAccept-Language: en-us\n\rAccept-Encoding: gzip, deflate\n\rConnection: keep-alive\n\r\n\r"
|
131
|
+
# => "GET /people/are/friendly HTTP/1.1\n\rHost: localhost:2000\n\rAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n\rCookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\n\rUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\n\rAccept-Language: en-us\n\rAccept-Encoding: gzip, deflate\n\rConnection: keep-alive\n\r\n\r"
|
132
|
+
# => "GET /girls?sexy=true HTTP/1.1\n\rHost: localhost:2000\n\rAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n\rCookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\n\rUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\n\rAccept-Language: en-us\n\rAccept-Encoding: gzip, deflate\n\rConnection: keep-alive\n\r\n\r"
|
133
|
+
# chunked => "17d; ignored data=boaz\r\nGET / HTTP/1.1\r\nHost: localhost:3000\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nCookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nc\r\n\r\nparsed as:\r\n\r\n4f4\r\n{:raw=>\"GET / HTTP/1.1\\r\\nHost: localhost:3000\\r\\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\\r\\nCookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\\r\\nAccept-Language: en-us\\r\\nAccept-Encoding: gzip, deflate\\r\\nConnection: keep-alive\\r\\n\\r\\n\", :plezi_service=>#<Plezi::BasicService:0x007ff4daab5ac8 @handler=Plezi::HTTPEcho, @socket=#<TCPSocket:fd 9>, @in_que=\"\", @out_que=[], @locker=#<Mutex:0x007ff4daab5a28>, @parameters={:protocol=>Plezi::HTTPProtocol, :handler=>Plezi::HTTPEcho}, @protocol=Plezi::HTTPProtocol>, :params=>{}, :cookies=>{:user_token=>\"2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\"}, :method=>\"GET\", :query=>\"/\", :original_path=>\"/\", :path=>\"/\", :version=>\"HTTP/1.1\", \"host\"=>\"localhost:3000\", \"accept\"=>\"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\", \"cookie\"=>\"user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w\", \"user-agent\"=>\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25\", \"accept-language\"=>\"en-us\", \"accept-encoding\"=>\"gzip, deflate\", \"connection\"=>\"keep-alive\"}\r\n0\r\n\r\n"
|