rackful 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/example/config.ru CHANGED
@@ -1,7 +1,10 @@
1
+ # Load core functionality:
1
2
  require 'rackful'
2
- require 'rackful/header_spoofing'
3
- require 'rackful/method_spoofing'
4
- require 'rackful/relative_location'
3
+
4
+ # Load extra middlewares: ({Rackful::MethodSpoofing}, {Rackful::HeaderSpoofing},
5
+ # Rackful::RelativeLocation})
6
+ require 'rackful/middleware'
7
+
5
8
  require 'digest/md5'
6
9
 
7
10
  # The class of the object we're going to serve:
data/lib/rackful.rb CHANGED
@@ -1,6 +1,6 @@
1
- require 'rackful_path.rb'
2
- require 'rackful_request.rb'
3
- require 'rackful_serializer.rb'
4
- require 'rackful_resource.rb'
5
- require 'rackful_http_status.rb'
6
- require 'rackful_server.rb'
1
+ require 'rackful/path.rb'
2
+ require 'rackful/request.rb'
3
+ require 'rackful/serializer.rb'
4
+ require 'rackful/resource.rb'
5
+ require 'rackful/http_status.rb'
6
+ require 'rackful/server.rb'
@@ -1,6 +1,6 @@
1
1
  # Required for parsing:
2
- require 'rackful_resource.rb'
3
- require 'rackful_serializer.rb'
2
+ require 'rackful/resource.rb'
3
+ require 'rackful/serializer.rb'
4
4
 
5
5
  # Required for running
6
6
  require 'rexml/rexml'
@@ -10,25 +10,30 @@ module Rackful
10
10
 
11
11
  =begin markdown
12
12
  Exception which represents an HTTP Status response.
13
- @since 0.1.0
14
13
  @abstract
15
14
  =end
16
15
  class HTTPStatus < RuntimeError
17
16
 
18
17
 
19
18
  include Resource
19
+
20
+
20
21
  attr_reader :status, :headers, :to_rackful
21
22
 
22
23
 
23
24
  =begin markdown
24
- @param message [String] XHTML
25
- @param status [Symbol, Integer] e.g. `404` or `:not_found`
26
- @param headers [Hash] HTTP response headers
25
+ @param [Symbol, Integer] status e.g. `404` or `:not_found`
26
+ @param [String] message XHTML
27
+ @param [ { Symbol => Object }, { String => String } ] info
28
+ * If the Hash is indexed by {Symbol}s, then the values will be returned in
29
+ the response body.
30
+ * If the Hash is indexed by {String}s, the +key => value+ pairs are returned
31
+ as response headers.
27
32
  =end
28
33
  def initialize status, message = nil, info = {}
29
34
  self.path = Request.current.path
30
35
  @status = status_code status
31
- raise "Wrong status: #{status}" if 0 == @status
36
+ raise "Wrong status: #{status}" if 0 === @status
32
37
  message ||= ''
33
38
  @headers = {}
34
39
  @to_rackful = {}
@@ -53,30 +58,42 @@ class HTTPStatus < RuntimeError
53
58
  errors.puts "Info: #{@to_rackful.inspect}"
54
59
  end
55
60
  end
61
+
62
+
63
+ def title
64
+ "#{status} #{HTTP_STATUS_CODES[status]}"
65
+ end
56
66
 
57
67
 
58
68
  class XHTML < ::Rackful::XHTML
59
69
 
60
70
 
61
- HTTP_STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES
62
-
63
-
64
71
  def header
65
- <<EOS
66
- <title>#{self.resource.status} #{HTTP_STATUS_CODES[self.resource.status]}</title>
67
- </head><body>
68
- <h1>HTTP/1.1 #{self.resource.status} #{HTTP_STATUS_CODES[self.resource.status]}</h1>
69
- <div id="rackful_description">#{self.resource.message}</div>
72
+ super + <<EOS
73
+ <h1>HTTP/1.1 #{Rack::Utils.escape_html(resource.title)}</h1>
74
+ <div id="rackful_description">#{resource.message}</div>
70
75
  EOS
71
76
  end
72
77
 
73
78
 
74
- def headers
75
- self.resource.headers
76
- end
79
+ def headers; self.resource.headers; end
80
+
81
+
82
+ end # class HTTPStatus::XHTML
77
83
 
78
84
 
79
- end # class HTTPStatus::XHTML
85
+ #~ class JSON < ::Rackful::JSON
86
+ #~
87
+ #~
88
+ #~ def headers; self.resource.headers; end
89
+ #~
90
+ #~
91
+ #~ def each &block
92
+ #~ super( [ self.resource.message, self.resource.to_rackful ], &block )
93
+ #~ end
94
+ #~
95
+ #~
96
+ #~ end # class HTTPStatus::XHTML
80
97
 
81
98
 
82
99
  add_serializer XHTML, 1.0
@@ -88,7 +105,6 @@ end # class Rackful::HTTPStatus
88
105
  =begin markdown
89
106
  @abstract Base class for HTTP status codes with only a simple text message, or
90
107
  no message at all.
91
- @since 0.1.0
92
108
  =end
93
109
  class HTTPSimpleStatus < HTTPStatus
94
110
 
@@ -101,7 +117,6 @@ class HTTPSimpleStatus < HTTPStatus
101
117
  end
102
118
 
103
119
 
104
- # @since 0.1.0
105
120
  class HTTP201Created < HTTPStatus
106
121
 
107
122
  def initialize locations
@@ -133,7 +148,6 @@ class HTTP201Created < HTTPStatus
133
148
  end # class HTTP201Created
134
149
 
135
150
 
136
- # @since 0.1.0
137
151
  class HTTP202Accepted < HTTPStatus
138
152
 
139
153
  def initialize location = nil
@@ -152,7 +166,6 @@ class HTTP202Accepted < HTTPStatus
152
166
  end # class HTTP202Accepted
153
167
 
154
168
 
155
- # @since 0.1.0
156
169
  class HTTP301MovedPermanently < HTTPStatus
157
170
 
158
171
  def initialize location
@@ -167,7 +180,6 @@ class HTTP301MovedPermanently < HTTPStatus
167
180
  end
168
181
 
169
182
 
170
- # @since 0.1.0
171
183
  class HTTP303SeeOther < HTTPStatus
172
184
 
173
185
  def initialize location
@@ -182,17 +194,15 @@ class HTTP303SeeOther < HTTPStatus
182
194
  end
183
195
 
184
196
 
185
- # @since 0.1.0
186
197
  class HTTP304NotModified < HTTPStatus
187
198
 
188
- def initialize location
189
- super( 304, nil, self.resource.default_headers )
199
+ def initialize
200
+ super( 304 )
190
201
  end
191
202
 
192
203
  end
193
204
 
194
205
 
195
- # @since 0.1.0
196
206
  class HTTP307TemporaryRedirect < HTTPStatus
197
207
 
198
208
  def initialize location
@@ -207,17 +217,13 @@ class HTTP307TemporaryRedirect < HTTPStatus
207
217
  end
208
218
 
209
219
 
210
- # @since 0.1.0
211
220
  class HTTP400BadRequest < HTTPSimpleStatus; end
212
221
 
213
- # @since 0.1.0
214
222
  class HTTP403Forbidden < HTTPSimpleStatus; end
215
223
 
216
- # @since 0.1.0
217
224
  class HTTP404NotFound < HTTPSimpleStatus; end
218
225
 
219
226
 
220
- # @since 0.1.0
221
227
  class HTTP405MethodNotAllowed < HTTPStatus
222
228
 
223
229
  def initialize methods
@@ -228,7 +234,6 @@ class HTTP405MethodNotAllowed < HTTPStatus
228
234
  end
229
235
 
230
236
 
231
- # @since 0.1.0
232
237
  class HTTP406NotAcceptable < HTTPStatus
233
238
 
234
239
  def initialize content_types
@@ -239,17 +244,13 @@ class HTTP406NotAcceptable < HTTPStatus
239
244
  end
240
245
 
241
246
 
242
- # @since 0.1.0
243
247
  class HTTP409Conflict < HTTPSimpleStatus; end
244
248
 
245
- # @since 0.1.0
246
249
  class HTTP410Gone < HTTPSimpleStatus; end
247
250
 
248
- # @since 0.1.0
249
251
  class HTTP411LengthRequired < HTTPSimpleStatus; end
250
252
 
251
253
 
252
- # @since 0.1.0
253
254
  class HTTP412PreconditionFailed < HTTPStatus
254
255
 
255
256
  def initialize header = nil
@@ -265,24 +266,20 @@ class HTTP412PreconditionFailed < HTTPStatus
265
266
  end
266
267
 
267
268
 
268
- # @since 0.1.0
269
269
  class HTTP415UnsupportedMediaType < HTTPStatus
270
270
 
271
271
  def initialize media_types
272
- super 405, '',
272
+ super 415, '',
273
273
  :'Supported media-type(s):' => media_types
274
274
  end
275
275
 
276
276
  end
277
277
 
278
278
 
279
- # @since 0.1.0
280
279
  class HTTP422UnprocessableEntity < HTTPSimpleStatus; end
281
280
 
282
- # @since 0.1.0
283
281
  class HTTP501NotImplemented < HTTPSimpleStatus; end
284
282
 
285
- # @since 0.1.0
286
283
  class HTTP503ServiceUnavailable < HTTPSimpleStatus; end
287
284
 
288
285
  end # module Rackful
@@ -0,0 +1,3 @@
1
+ require 'rackful/middleware/header_spoofing.rb'
2
+ require 'rackful/middleware/method_spoofing.rb'
3
+ require 'rackful/middleware/relative_location.rb'
@@ -26,7 +26,6 @@ This can be useful if you want to specify certain request headers from within
26
26
  a normal web browser.
27
27
  @example Using this middleware
28
28
  use Rackful::HeaderSpoofing
29
- @since 0.0.1
30
29
  =end
31
30
  class Rackful::HeaderSpoofing
32
31
 
@@ -64,10 +63,10 @@ def before_call env
64
63
  end
65
64
 
66
65
  def after_call env
67
- if original_query_string = env['rackful.header_spoofing.query_string']
68
- env['rackful.header_spoofing.query_string'] = env['QUERY_STRING']
69
- env['QUERY_STRING'] = original_query_string
70
- end
66
+ #if original_query_string = env['rackful.header_spoofing.query_string']
67
+ #env['rackful.header_spoofing.query_string'] = env['QUERY_STRING']
68
+ #env['QUERY_STRING'] = original_query_string
69
+ #end
71
70
  end
72
71
 
73
72
  end # Rackful::HeaderSpoofing
@@ -35,7 +35,6 @@ In that case, you can put the parameters in a `POST` body, like this:
35
35
  param_1=hello&param_2=world&param_3=...
36
36
  @example Using this middleware
37
37
  use Rackful::MethodSpoofing
38
- @since 0.0.1
39
38
  =end
40
39
  class Rackful::MethodSpoofing
41
40
 
@@ -29,7 +29,6 @@ Differences with {Rack::RelativeRedirect}:
29
29
  - uses Rack::Request::base_url for creating absolute URIs.
30
30
  - the `Location:` header, if present, is always rectified, independent of the
31
31
  HTTP status code.
32
- @since 0.0.1
33
32
  =end
34
33
  class Rackful::RelativeLocation
35
34
 
@@ -0,0 +1,179 @@
1
+ # Required for parsing:
2
+
3
+ # Required for running:
4
+ require 'rack/utils'
5
+
6
+
7
+ # A String monkeypatch
8
+ # @private
9
+ class String
10
+
11
+ # @return [Rackful::Path]
12
+ def to_path; Rackful::Path.new(self); end
13
+
14
+ end
15
+
16
+
17
+ module Rackful
18
+
19
+
20
+ # Relative URI (a path)
21
+ class Path < String
22
+
23
+
24
+ # @return [self]
25
+ def to_path; self; end
26
+
27
+
28
+ # @return [Path] a copy of `self`, with a trailing slash.
29
+ def slashify
30
+ r = self.dup
31
+ r << '/' if '/' != r[-1,1]
32
+ r
33
+ end
34
+
35
+
36
+ # Adds a trailing slash to `self` if necessary.
37
+ # @return [self]
38
+ def slashify!
39
+ if '/' != self[-1,1]
40
+ self << '/'
41
+ else
42
+ nil
43
+ end
44
+ self
45
+ end
46
+
47
+
48
+ # @return [Path]a copy of `self` without a trailing slash.
49
+ def unslashify
50
+ r = self.dup
51
+ r = r.chomp( '/' ) if '/' == r[-1,1]
52
+ r
53
+ end
54
+
55
+
56
+ # Removes a trailing slash from `self`.
57
+ # @return [self]
58
+ def unslashify!
59
+ if '/' == self[-1,1]
60
+ self.chomp! '/'
61
+ else
62
+ nil
63
+ end
64
+ self
65
+ end
66
+
67
+
68
+ # @param [Encoding] encoding the character encoding to presume for `self`
69
+ # @return [String] the unescaped version of `self`
70
+ def unescape( encoding = Encoding::UTF_8 ); Rack::Utils.unescape(self, encoding); end
71
+
72
+
73
+ # @return [Array<String>] Unencoded segments
74
+ def segments( encoding = Encoding::UTF_8 )
75
+ r = self.split('/').collect { |s| Rack::Utils.unescape( s, encoding ) }
76
+ r.shift
77
+ r
78
+ end
79
+
80
+
81
+ # Turns a relative URI (starting with `/`) into a relative path (starting with `./`)
82
+ # @param path [Path]
83
+ # @return [String] a relative URI
84
+ def relative base_path = Request.current.base_path
85
+ case self
86
+ when base_path
87
+ # RFC2396, Section 4.2
88
+ return ''
89
+ when %r{(?:\A|/)\.\.?(?:/|\z)}
90
+ # self has abnormal absolute path,
91
+ # like "/./", "/../", "/x/../", ...
92
+ return self.dup
93
+ end
94
+
95
+ src_path = base_path.scan(%r{(?:\A|[^/]+)/})
96
+ dst_path = self.scan(%r{(?:\A|[^/]+)/?})
97
+
98
+ # discard same parts
99
+ while !dst_path.empty? && dst_path.first == src_path.first
100
+ src_path.shift
101
+ dst_path.shift
102
+ end
103
+
104
+ tmp = dst_path.join
105
+
106
+ # calculate
107
+ if src_path.empty?
108
+ if tmp.empty?
109
+ return './'
110
+ elsif dst_path.first.include?(':') # (see RFC2396 Section 5)
111
+ return './' + tmp
112
+ else
113
+ return tmp
114
+ end
115
+ end
116
+
117
+ return '../' * src_path.size + tmp
118
+ end
119
+
120
+
121
+ end # class Path
122
+
123
+
124
+ end # module Rackful
125
+
126
+
127
+ #~ # Monkeypatch to this stdlib class.
128
+ #~ class URI::Generic
129
+ #~
130
+ #~ # @see http://www.w3.org/TR/html401/struct/links.html#adef-rel the HTML `rel` attribute.
131
+ #~ attr_accessor :rel
132
+ #~
133
+ #~ # @see http://www.w3.org/TR/html401/struct/links.html#adef-rev the HTML `rev` attribute.
134
+ #~ attr_accessor :rev
135
+ #~
136
+ #~ def to_xhtml base_path, encoding = Encoding::UTF_8
137
+ #~ retval = "<a href=\"#{self.route_from(base_path)}\"".encode encoding
138
+ #~ retval << " rel=\"#{self.rel}\"" if self.rel
139
+ #~ retval << " rev=\"#{self.rev}\"" if self.rev
140
+ #~ retval << '>'
141
+ #~ if self.relative? && ! self.query && ! self.fragment
142
+ #~ retval << Rack::Utils.escape_html(
143
+ #~ Rack::Utils.unescape( self.route_from(base_path).to_s, encoding )
144
+ #~ )
145
+ #~ else
146
+ #~ retval << self.to_s
147
+ #~ end
148
+ #~ retval << '</a>'
149
+ #~ retval
150
+ #~ end
151
+ #~
152
+ #~ # @return [URI::Generic]
153
+ #~ def slashify
154
+ #~ r = self.dup
155
+ #~ r.path = r.path.unslashify
156
+ #~ r
157
+ #~ end
158
+ #~
159
+ #~ # @return [self, nil]
160
+ #~ def slashify!
161
+ #~ self.path.slashify! && self
162
+ #~ end
163
+ #~
164
+ #~ # @return [URI::Generic]
165
+ #~ def unslashify
166
+ #~ r = self.dup
167
+ #~ r.path = r.path.unslashify
168
+ #~ r
169
+ #~ end
170
+ #~
171
+ #~ # @return [self, nil]
172
+ #~ def unslashify!
173
+ #~ self.path.unslashify! && self
174
+ #~ end
175
+ #~
176
+ #~ end # class ::URI::Generic
177
+
178
+
179
+