rackful 0.1.2 → 0.1.3

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/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
+