utopia 0.9.57 → 0.9.58

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,19 @@
2
2
  # Copyright 2010 Samuel Williams. All rights reserved.
3
3
  # See <utopia.rb> for licensing details.
4
4
 
5
+ class Rack::Request
6
+ def url_with_path(path = "")
7
+ url = scheme + "://"
8
+ url << host
9
+
10
+ if scheme == "https" && port != 443 || scheme == "http" && port != 80
11
+ url << ":#{port}"
12
+ end
13
+
14
+ url << path
15
+ end
16
+ end
17
+
5
18
  class Rack::Response
6
19
  def do_not_cache!
7
20
  self["Cache-Control"] = "no-cache, must-revalidate"
@@ -14,4 +27,8 @@ class Rack::Response
14
27
  self["Expires"] = (Time.now + duration).httpdate
15
28
  end
16
29
  end
30
+
31
+ def content_type!(value)
32
+ self["Content-Type"] = value.to_s
33
+ end
17
34
  end
@@ -31,6 +31,7 @@ module Utopia
31
31
  403 => "Access Forbidden",
32
32
  404 => "Resource Not Found",
33
33
  405 => "Unsupported Method",
34
+ 416 => "Byte range unsatisfiable",
34
35
  500 => "Internal Server Error",
35
36
  501 => "Not Implemented",
36
37
  503 => "Service Unavailable"
@@ -5,6 +5,7 @@
5
5
  require 'pathname'
6
6
  require 'logger'
7
7
 
8
+ require 'utopia/http_status_codes'
8
9
  require 'utopia/extensions/rack'
9
10
 
10
11
  module Utopia
@@ -15,6 +16,16 @@ module Utopia
15
16
  def self.default_root(subdir = "pages")
16
17
  Pathname.new(Dir.pwd).join(subdir).cleanpath.to_s
17
18
  end
19
+
20
+ def self.failure(status = 500, message = "Non-specific error")
21
+ body = "#{HTTP_STATUS_DESCRIPTIONS[status] || status.to_s}: #{message}"
22
+
23
+ return [status, {
24
+ "Content-Type" => "text/plain",
25
+ "Content-Length" => body.size.to_s,
26
+ "X-Cascade" => "pass"
27
+ }, [body]]
28
+ end
18
29
  end
19
30
  end
20
31
 
@@ -1,6 +1,7 @@
1
1
  # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
2
  # Copyright 2010 Samuel Williams. All rights reserved.
3
3
  # See <utopia.rb> for licensing details.
4
+
4
5
  require 'utopia/middleware'
5
6
  require 'utopia/path'
6
7
 
@@ -50,11 +51,14 @@ module Utopia
50
51
  @root = root
51
52
  @path = path
52
53
  @etag = Digest::SHA1.hexdigest("#{File.size(full_path)}#{mtime_date}")
54
+
55
+ @range = nil
53
56
  end
54
57
 
55
58
  attr :root
56
59
  attr :path
57
60
  attr :etag
61
+ attr :range
58
62
 
59
63
  # Fit in with Rack::Sendfile
60
64
  def to_path
@@ -74,8 +78,15 @@ module Utopia
74
78
  end
75
79
 
76
80
  def each
77
- File.open(full_path, "rb") do |fp|
78
- while part = fp.read(8192)
81
+ File.open(full_path, "rb") do |file|
82
+ file.seek(@range.begin)
83
+ remaining = @range.end - @range.begin+1
84
+
85
+ while remaining > 0
86
+ break unless part = file.read([8192, remaining].min)
87
+
88
+ remaining -= part.length
89
+
79
90
  yield part
80
91
  end
81
92
  end
@@ -93,6 +104,38 @@ module Utopia
93
104
 
94
105
  return true
95
106
  end
107
+
108
+ def serve(env, response_headers)
109
+ ranges = Rack::Utils.byte_ranges(env, size)
110
+ response = [200, response_headers, self]
111
+
112
+ # LOG.info("Requesting ranges: #{ranges.inspect} (#{size})")
113
+
114
+ if ranges.nil? || ranges.length > 1
115
+ # No ranges, or multiple ranges (which we don't support):
116
+ # TODO: Support multiple byte-ranges
117
+ response[0] = 200
118
+ response[1]["Content-Length"] = size.to_s
119
+ @range = 0..size-1
120
+ elsif ranges.empty?
121
+ # Unsatisfiable. Return error, and file size:
122
+ response = Middleware::failure(416, "Invalid range specified.")
123
+ response[1]["Content-Range"] = "bytes */#{size}"
124
+ return response
125
+ else
126
+ # Partial content:
127
+ @range = ranges[0]
128
+ response[0] = 206
129
+ response[1]["Content-Range"] = "bytes #{@range.begin}-#{@range.end}/#{size}"
130
+ response[1]["Content-Length"] = (@range.end - @range.begin+1).to_s
131
+ size = @range.end - @range.begin + 1
132
+ end
133
+
134
+ # LOG.info("Response for #{self.full_path}: #{response.inspect}")
135
+ LOG.info "Serving file #{full_path.inspect}, range #{@range.inspect}"
136
+
137
+ return response
138
+ end
96
139
  end
97
140
 
98
141
  def load_mime_types(types)
@@ -141,15 +184,15 @@ module Utopia
141
184
  def initialize(app, options = {})
142
185
  @app = app
143
186
  @root = options[:root] || Utopia::Middleware::default_root
144
-
187
+
145
188
  if options[:types]
146
189
  @extensions = load_mime_types(options[:types])
147
190
  else
148
191
  @extensions = load_mime_types(MIME_TYPES[:default])
149
192
  end
150
-
193
+
151
194
  @cache_control = options[:cache_control] || "public, max-age=3600"
152
-
195
+
153
196
  LOG.info "** #{self.class.name}: Running in #{@root} with #{extensions.size} filetypes"
154
197
  # LOG.info @extensions.inspect
155
198
  end
@@ -203,21 +246,21 @@ module Utopia
203
246
  def call(env)
204
247
  request = Rack::Request.new(env)
205
248
  ext = File.extname(request.path_info)
249
+
206
250
  if @extensions.key? ext.downcase
207
251
  path = Path.create(request.path_info).simplify
208
-
252
+
209
253
  if file = fetch_file(path)
210
254
  response_headers = {
211
255
  "Last-Modified" => file.mtime_date,
212
256
  "Content-Type" => @extensions[ext],
213
257
  "Cache-Control" => @cache_control,
214
258
  "ETag" => file.etag,
259
+ "Accept-Ranges" => "bytes"
215
260
  }
216
261
 
217
262
  if file.modified?(env)
218
- response_headers["Content-Length"] = file.size.to_s
219
-
220
- return [200, response_headers, file]
263
+ return file.serve(env, response_headers)
221
264
  else
222
265
  return [304, response_headers, []]
223
266
  end
@@ -1,8 +1,8 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <?r response["Content-Type"] = "text/html; charset=utf-8" ?>
5
- <?r response["Cache-Control"] = "max-age=3600" ?>
4
+ <?r response.content_type! "text/html; charset=utf-8" ?>
5
+ <?r response.cache! ?>
6
6
 
7
7
  <?r if title = (attributes["title"] || @title) ?>
8
8
  <title>#{title.gsub(/<.*?>/, "")} - Utopia</title>
@@ -6,7 +6,7 @@ module Utopia
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 9
9
- TINY = 57
9
+ TINY = 58
10
10
 
11
11
  STRING = [MAJOR, MINOR, TINY].join('.')
12
12
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utopia
3
3
  version: !ruby/object:Gem::Version
4
- hash: 73
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 9
9
- - 57
10
- version: 0.9.57
8
+ - 58
9
+ version: 0.9.58
11
10
  platform: ruby
12
11
  authors:
13
12
  - Samuel Williams
@@ -15,17 +14,16 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-08-30 00:00:00 Z
17
+ date: 2012-01-12 00:00:00 +13:00
18
+ default_executable: utopia
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mime-types
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
24
  requirements:
26
25
  - - ">="
27
26
  - !ruby/object:Gem::Version
28
- hash: 3
29
27
  segments:
30
28
  - 0
31
29
  version: "0"
@@ -35,11 +33,9 @@ dependencies:
35
33
  name: rack
36
34
  prerelease: false
37
35
  requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
36
  requirements:
40
37
  - - ">="
41
38
  - !ruby/object:Gem::Version
42
- hash: 3
43
39
  segments:
44
40
  - 0
45
41
  version: "0"
@@ -49,11 +45,9 @@ dependencies:
49
45
  name: rack-cache
50
46
  prerelease: false
51
47
  requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
48
  requirements:
54
49
  - - ">="
55
50
  - !ruby/object:Gem::Version
56
- hash: 3
57
51
  segments:
58
52
  - 0
59
53
  version: "0"
@@ -63,11 +57,9 @@ dependencies:
63
57
  name: rack-contrib
64
58
  prerelease: false
65
59
  requirement: &id004 !ruby/object:Gem::Requirement
66
- none: false
67
60
  requirements:
68
61
  - - ">="
69
62
  - !ruby/object:Gem::Version
70
- hash: 3
71
63
  segments:
72
64
  - 0
73
65
  version: "0"
@@ -77,11 +69,9 @@ dependencies:
77
69
  name: rmagick
78
70
  prerelease: false
79
71
  requirement: &id005 !ruby/object:Gem::Requirement
80
- none: false
81
72
  requirements:
82
73
  - - ">="
83
74
  - !ruby/object:Gem::Version
84
- hash: 3
85
75
  segments:
86
76
  - 0
87
77
  version: "0"
@@ -155,6 +145,7 @@ files:
155
145
  - lib/utopia/xnode.rb
156
146
  - lib/utopia.rb
157
147
  - bin/utopia
148
+ has_rdoc: true
158
149
  homepage: http://www.oriontransfer.co.nz/software/utopia
159
150
  licenses: []
160
151
 
@@ -164,27 +155,23 @@ rdoc_options: []
164
155
  require_paths:
165
156
  - lib
166
157
  required_ruby_version: !ruby/object:Gem::Requirement
167
- none: false
168
158
  requirements:
169
159
  - - ">="
170
160
  - !ruby/object:Gem::Version
171
- hash: 3
172
161
  segments:
173
162
  - 0
174
163
  version: "0"
175
164
  required_rubygems_version: !ruby/object:Gem::Requirement
176
- none: false
177
165
  requirements:
178
166
  - - ">="
179
167
  - !ruby/object:Gem::Version
180
- hash: 3
181
168
  segments:
182
169
  - 0
183
170
  version: "0"
184
171
  requirements: []
185
172
 
186
173
  rubyforge_project:
187
- rubygems_version: 1.8.7
174
+ rubygems_version: 1.3.6
188
175
  signing_key:
189
176
  specification_version: 3
190
177
  summary: Utopia is a framework for building websites.