strelka 0.0.1pre4 → 0.0.1.pre129
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.
- data/History.rdoc +1 -1
- data/IDEAS.rdoc +62 -0
- data/Manifest.txt +38 -7
- data/README.rdoc +124 -5
- data/Rakefile +22 -6
- data/bin/leash +102 -157
- data/contrib/hoetemplate/.autotest.erb +23 -0
- data/contrib/hoetemplate/History.rdoc.erb +4 -0
- data/contrib/hoetemplate/Manifest.txt.erb +8 -0
- data/contrib/hoetemplate/README.rdoc.erb +17 -0
- data/contrib/hoetemplate/Rakefile.erb +24 -0
- data/contrib/hoetemplate/data/file_name/apps/file_name_app +36 -0
- data/contrib/hoetemplate/data/file_name/templates/layout.tmpl.erb +13 -0
- data/contrib/hoetemplate/data/file_name/templates/top.tmpl.erb +8 -0
- data/contrib/hoetemplate/lib/file_name.rb.erb +18 -0
- data/contrib/hoetemplate/spec/file_name_spec.rb.erb +21 -0
- data/data/strelka/apps/hello-world +30 -0
- data/lib/strelka/app/defaultrouter.rb +49 -30
- data/lib/strelka/app/errors.rb +121 -0
- data/lib/strelka/app/exclusiverouter.rb +40 -0
- data/lib/strelka/app/filters.rb +18 -7
- data/lib/strelka/app/negotiation.rb +122 -0
- data/lib/strelka/app/parameters.rb +171 -14
- data/lib/strelka/app/paramvalidator.rb +751 -0
- data/lib/strelka/app/plugins.rb +66 -46
- data/lib/strelka/app/restresources.rb +499 -0
- data/lib/strelka/app/router.rb +73 -0
- data/lib/strelka/app/routing.rb +140 -18
- data/lib/strelka/app/templating.rb +12 -3
- data/lib/strelka/app.rb +174 -24
- data/lib/strelka/constants.rb +0 -20
- data/lib/strelka/exceptions.rb +29 -0
- data/lib/strelka/httprequest/acceptparams.rb +377 -0
- data/lib/strelka/httprequest/negotiation.rb +257 -0
- data/lib/strelka/httprequest.rb +155 -7
- data/lib/strelka/httpresponse/negotiation.rb +579 -0
- data/lib/strelka/httpresponse.rb +140 -0
- data/lib/strelka/logging.rb +4 -1
- data/lib/strelka/mixins.rb +53 -0
- data/lib/strelka.rb +22 -1
- data/spec/data/error.tmpl +1 -0
- data/spec/lib/constants.rb +0 -1
- data/spec/lib/helpers.rb +21 -0
- data/spec/strelka/app/defaultrouter_spec.rb +41 -35
- data/spec/strelka/app/errors_spec.rb +212 -0
- data/spec/strelka/app/exclusiverouter_spec.rb +220 -0
- data/spec/strelka/app/filters_spec.rb +196 -0
- data/spec/strelka/app/negotiation_spec.rb +73 -0
- data/spec/strelka/app/parameters_spec.rb +149 -0
- data/spec/strelka/app/paramvalidator_spec.rb +1059 -0
- data/spec/strelka/app/plugins_spec.rb +26 -19
- data/spec/strelka/app/restresources_spec.rb +393 -0
- data/spec/strelka/app/router_spec.rb +63 -0
- data/spec/strelka/app/routing_spec.rb +183 -9
- data/spec/strelka/app/templating_spec.rb +1 -2
- data/spec/strelka/app_spec.rb +265 -32
- data/spec/strelka/exceptions_spec.rb +53 -0
- data/spec/strelka/httprequest/acceptparams_spec.rb +282 -0
- data/spec/strelka/httprequest/negotiation_spec.rb +246 -0
- data/spec/strelka/httprequest_spec.rb +204 -14
- data/spec/strelka/httpresponse/negotiation_spec.rb +464 -0
- data/spec/strelka/httpresponse_spec.rb +114 -0
- data/spec/strelka/mixins_spec.rb +99 -0
- data.tar.gz.sig +1 -0
- metadata +175 -79
- metadata.gz.sig +2 -0
- data/IDEAS.textile +0 -174
- data/data/strelka/apps/strelka-admin +0 -65
- data/data/strelka/apps/strelka-setup +0 -26
- data/data/strelka/bootstrap-config.rb +0 -34
- data/data/strelka/templates/admin/console.tmpl +0 -21
- data/data/strelka/templates/layout.tmpl +0 -30
- data/lib/strelka/process.rb +0 -19
data/lib/strelka/httprequest.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'yajl'
|
4
|
+
require 'yaml'
|
3
5
|
require 'uri'
|
4
6
|
|
5
7
|
require 'mongrel2/httprequest'
|
6
8
|
require 'strelka' unless defined?( Strelka )
|
9
|
+
require 'strelka/httpresponse'
|
7
10
|
|
8
11
|
# An HTTP request class.
|
9
12
|
class Strelka::HTTPRequest < Mongrel2::HTTPRequest
|
@@ -14,11 +17,23 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
|
|
14
17
|
register_request_type( self, *HTTP::RFC2616_VERBS )
|
15
18
|
|
16
19
|
|
20
|
+
### Override the type of response returned by this request type.
|
21
|
+
def self::response_class
|
22
|
+
return Strelka::HTTPResponse
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
#################################################################
|
27
|
+
### I N S T A N C E M E T H O D S
|
28
|
+
#################################################################
|
29
|
+
|
17
30
|
### Initialize some additional stuff for Strelka requests.
|
18
31
|
def initialize( * ) # :notnew:
|
19
32
|
super
|
20
|
-
@uri
|
21
|
-
@verb
|
33
|
+
@uri = nil
|
34
|
+
@verb = self.headers[:method].to_sym
|
35
|
+
@params = nil
|
36
|
+
@notes = Hash.new( &method(:autovivify) )
|
22
37
|
end
|
23
38
|
|
24
39
|
|
@@ -29,24 +44,157 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
|
|
29
44
|
# The HTTP verb of the request (as a Symbol)
|
30
45
|
attr_accessor :verb
|
31
46
|
|
47
|
+
# The parameters hash parsed from the request
|
48
|
+
attr_writer :params
|
49
|
+
|
50
|
+
# A Hash that plugins can use to pass data amongst themselves. The missing-key
|
51
|
+
# callback is set to auto-create nested sub-hashes.
|
52
|
+
attr_reader :notes
|
53
|
+
|
32
54
|
|
33
55
|
### Return a URI object parsed from the URI of the request.
|
56
|
+
###
|
57
|
+
### # "GET /user/1/profile HTTP/1.1"
|
58
|
+
### request.uri
|
59
|
+
### # => #<URI::HTTP:0x007fe34d16b2e0 URL:http://localhost:8080/user/1/profile>
|
34
60
|
def uri
|
35
|
-
|
61
|
+
unless @uri
|
62
|
+
# :TODO: Make this detect https scheme once I figure out how to
|
63
|
+
# detect it.
|
64
|
+
uri = "http://%s%s" % [
|
65
|
+
self.headers.host,
|
66
|
+
self.headers.uri
|
67
|
+
]
|
68
|
+
@uri = URI( uri )
|
69
|
+
end
|
70
|
+
|
71
|
+
return @uri
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
### Return a URI object for the base of the app being run. This is the #uri with the
|
76
|
+
### #app_path and any query string removed.
|
77
|
+
###
|
78
|
+
### # For a handler with a route of '/user', for the request:
|
79
|
+
### # "GET /user/1/profile HTTP/1.1"
|
80
|
+
### request.base_uri
|
81
|
+
### # => #<URI::HTTP:0x007fe34d16b2e0 URL:http://localhost:8080/user>
|
82
|
+
def base_uri
|
83
|
+
rval = self.uri
|
84
|
+
rval.path = self.route
|
85
|
+
rval.query = nil
|
86
|
+
return rval
|
36
87
|
end
|
37
88
|
|
38
89
|
|
39
90
|
### Return the portion of the Request's path that was routed by Mongrel2. This and the
|
40
91
|
### #app_path make up the #path.
|
41
|
-
|
92
|
+
###
|
93
|
+
### # For a handler with a route of '/user', for the request:
|
94
|
+
### # "GET /user/1/profile HTTP/1.1"
|
95
|
+
### request.route
|
96
|
+
### # => "/user"
|
97
|
+
def route
|
42
98
|
return self.headers.pattern
|
43
99
|
end
|
100
|
+
alias_method :pattern, :route
|
44
101
|
|
45
102
|
|
46
|
-
### Return the portion of the Request's path relative to the
|
47
|
-
###
|
103
|
+
### Return the portion of the Request's path relative to the request's #route.
|
104
|
+
###
|
105
|
+
### # For a handler with a route of '/user', for the request:
|
106
|
+
### # "GET /user/1/profile HTTP/1.1"
|
107
|
+
### request.app_path
|
108
|
+
### # => "/1/profile"
|
48
109
|
def app_path
|
49
|
-
|
110
|
+
rval = self.uri.path.dup
|
111
|
+
rval.slice!( 0, self.route.length )
|
112
|
+
return rval
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
### Parse the request parameters and return them as a Hash. For GET requests, these are
|
117
|
+
### take from the query arguments, and for POST requests, from the
|
118
|
+
###
|
119
|
+
### # For a handler with a route of '/user', for the request:
|
120
|
+
### # "GET /user/1/profile?checkbox=1&checkbox=2&text=foo HTTP/1.1"
|
121
|
+
### # r.params
|
122
|
+
### # => {"checkbox"=>["1", "2"], "text"=>"foo"}
|
123
|
+
def params
|
124
|
+
unless @params
|
125
|
+
case self.verb
|
126
|
+
when :GET, :HEAD
|
127
|
+
@params = self.parse_query_args
|
128
|
+
when :POST, :PUT
|
129
|
+
@params = self.parse_form_data
|
130
|
+
else
|
131
|
+
self.log.debug "No parameters for a %s request." % [ self.verb ]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
return @params
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
#########
|
140
|
+
protected
|
141
|
+
#########
|
142
|
+
|
143
|
+
### Return a Hash of request query arguments.
|
144
|
+
### ?arg1=yes&arg2=no&arg3 #=> {'arg1' => 'yes', 'arg2' => 'no', 'arg3' => nil}
|
145
|
+
def parse_query_args
|
146
|
+
return {} if self.uri.query.nil?
|
147
|
+
return merge_query_args( URI.decode_www_form(self.uri.query) )
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
### Return a Hash of request form data.
|
152
|
+
def parse_form_data
|
153
|
+
case self.headers.content_type
|
154
|
+
when 'application/x-www-form-urlencoded'
|
155
|
+
return merge_query_args( URI.decode_www_form(self.body) )
|
156
|
+
when 'application/json', 'text/javascript'
|
157
|
+
return Yajl.load( self.body )
|
158
|
+
when 'text/x-yaml', 'application/x-yaml'
|
159
|
+
return YAML.load( self.body )
|
160
|
+
when 'multipart/form-data'
|
161
|
+
raise NotImplementedError, "%p doesn't handle multipart form data yet" %
|
162
|
+
[ self.class ]
|
163
|
+
else
|
164
|
+
raise Strelka::Error, "don't know how to handle %p form data" %
|
165
|
+
[ self.headers.content_type ]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
#######
|
171
|
+
private
|
172
|
+
#######
|
173
|
+
|
174
|
+
### Return the given +enum+ containing query arguments (such as those returned from
|
175
|
+
### URI.decode_www_form) as a Hash, combining multiple values for the same key
|
176
|
+
### into an Array.
|
177
|
+
def merge_query_args( enum )
|
178
|
+
return enum.inject({}) do |hash,(key,val)|
|
179
|
+
|
180
|
+
# If there's already a value in the Hash, turn it into an array if
|
181
|
+
# it's not already, and append the new value
|
182
|
+
if hash.key?( key )
|
183
|
+
hash[ key ] = [ hash[key] ] unless hash[ key ].is_a?( Array )
|
184
|
+
hash[ key ] << val
|
185
|
+
else
|
186
|
+
hash[ key ] = val
|
187
|
+
end
|
188
|
+
|
189
|
+
hash
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
### Create and return a Hash that will auto-vivify any values it is missing with
|
195
|
+
### another auto-vivifying Hash.
|
196
|
+
def autovivify( hash, key )
|
197
|
+
hash[ key ] = Hash.new( &method(:autovivify) )
|
50
198
|
end
|
51
199
|
|
52
200
|
end # class Strelka::HTTPRequest
|