Class: Utopia::Static::LocalFile

Inherits:
Object
  • Object
show all
Defined in:
lib/utopia/static.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root, path) ⇒ LocalFile

Returns a new instance of LocalFile.



68
69
70
71
72
73
74
# File 'lib/utopia/static.rb', line 68

def initialize(root, path)
	@root = root
	@path = path
	@etag = Digest::SHA1.hexdigest("#{File.size(full_path)}#{mtime_date}")

	@range = nil
end

Instance Attribute Details

#etagObject (readonly)

Returns the value of attribute etag.



78
79
80
# File 'lib/utopia/static.rb', line 78

def etag
  @etag
end

#pathObject (readonly)

Returns the value of attribute path.



77
78
79
# File 'lib/utopia/static.rb', line 77

def path
  @path
end

#rangeObject (readonly)

Returns the value of attribute range.



79
80
81
# File 'lib/utopia/static.rb', line 79

def range
  @range
end

#rootObject (readonly)

Returns the value of attribute root.



76
77
78
# File 'lib/utopia/static.rb', line 76

def root
  @root
end

Instance Method Details

#eachObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/utopia/static.rb', line 98

def each
	File.open(full_path, "rb") do |file|
		file.seek(@range.begin)
		remaining = @range.end - @range.begin+1

		while remaining > 0
			break unless part = file.read([8192, remaining].min)

			remaining -= part.length

			yield part
		end
	end
end

#full_pathObject



86
87
88
# File 'lib/utopia/static.rb', line 86

def full_path
	File.join(@root, @path.components)
end

#modified?(env) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/utopia/static.rb', line 113

def modified?(env)
	if modified_since = env['HTTP_IF_MODIFIED_SINCE']
		return false if File.mtime(full_path) <= Time.parse(modified_since)
	end

	if etags = env['HTTP_IF_NONE_MATCH']
		etags = etags.split(/\s*,\s*/)
		return false if etags.include?(etag) || etags.include?('*')
	end

	return true
end

#mtime_dateObject



90
91
92
# File 'lib/utopia/static.rb', line 90

def mtime_date
	File.mtime(full_path).httpdate
end

#serve(env, response_headers) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/utopia/static.rb', line 126

def serve(env, response_headers)
	ranges = Rack::Utils.byte_ranges(env, size)
	response = [200, response_headers, self]

	# LOG.info("Requesting ranges: #{ranges.inspect} (#{size})")

	if ranges == nil or ranges.size != 1
		# No ranges, or multiple ranges (which we don't support).
		# TODO: Support multiple byte-ranges, for now just send entire file:
		response[0] = 200
		response[1]["Content-Length"] = size.to_s
		@range = 0..size-1
	else
		# Partial content:
		@range = ranges[0]
		response[0] = 206
		response[1]["Content-Range"] = "bytes #{@range.begin}-#{@range.end}/#{size}"
		response[1]["Content-Length"] = (@range.end - @range.begin+1).to_s
		size = @range.end - @range.begin + 1
	end

	# LOG.debug {"Serving file #{full_path.inspect}, range #{@range.inspect}"}

	return response
end

#sizeObject



94
95
96
# File 'lib/utopia/static.rb', line 94

def size
	File.size(full_path)
end

#to_pathObject

Fit in with Rack::Sendfile



82
83
84
# File 'lib/utopia/static.rb', line 82

def to_path
	full_path
end