| Class | WEBrick::HTTPServlet::DefaultFileHandler |
| In: |
lib/webrick/httpservlet/filehandler.rb
|
| Parent: | AbstractServlet |
# File lib/webrick/httpservlet/filehandler.rb, line 22
22: def initialize(server, local_path)
23: super
24: @local_path = local_path
25: end
# File lib/webrick/httpservlet/filehandler.rb, line 27
27: def do_GET(req, res)
28: st = File::stat(@local_path)
29: mtime = st.mtime
30: res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
31:
32: if not_modified?(req, res, mtime, res['etag'])
33: res.body = ''
34: raise HTTPStatus::NotModified
35: elsif req['range']
36: make_partial_content(req, res, @local_path, st.size)
37: raise HTTPStatus::PartialContent
38: else
39: mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
40: res['content-type'] = mtype
41: res['content-length'] = st.size
42: res['last-modified'] = mtime.httpdate
43: res.body = open(@local_path, "rb")
44: end
45: end
# File lib/webrick/httpservlet/filehandler.rb, line 72
72: def make_partial_content(req, res, filename, filesize)
73: mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
74: unless ranges = HTTPUtils::parse_range_header(req['range'])
75: raise HTTPStatus::BadRequest,
76: "Unrecognized range-spec: \"#{req['range']}\""
77: end
78: open(filename, "rb"){|io|
79: if ranges.size > 1
80: time = Time.now
81: boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
82: body = ''
83: ranges.each{|range|
84: first, last = prepare_range(range, filesize)
85: next if first < 0
86: io.pos = first
87: content = io.read(last-first+1)
88: body << "--" << boundary << CRLF
89: body << "Content-Type: #{mtype}" << CRLF
90: body << "Content-Range: #{first}-#{last}/#{filesize}" << CRLF
91: body << CRLF
92: body << content
93: body << CRLF
94: }
95: raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
96: body << "--" << boundary << "--" << CRLF
97: res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
98: res.body = body
99: elsif range = ranges[0]
100: first, last = prepare_range(range, filesize)
101: raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
102: if last == filesize - 1
103: content = io.dup
104: content.pos = first
105: else
106: io.pos = first
107: content = io.read(last-first+1)
108: end
109: res['content-type'] = mtype
110: res['content-range'] = "#{first}-#{last}/#{filesize}"
111: res['content-length'] = last - first + 1
112: res.body = content
113: else
114: raise HTTPStatus::BadRequest
115: end
116: }
117: end
# File lib/webrick/httpservlet/filehandler.rb, line 47
47: def not_modified?(req, res, mtime, etag)
48: if ir = req['if-range']
49: begin
50: if Time.httpdate(ir) >= mtime
51: return true
52: end
53: rescue
54: if HTTPUtils::split_header_value(ir).member?(res['etag'])
55: return true
56: end
57: end
58: end
59:
60: if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime
61: return true
62: end
63:
64: if (inm = req['if-none-match']) &&
65: HTTPUtils::split_header_value(inm).member?(res['etag'])
66: return true
67: end
68:
69: return false
70: end
# File lib/webrick/httpservlet/filehandler.rb, line 119
119: def prepare_range(range, filesize)
120: first = range.first < 0 ? filesize + range.first : range.first
121: return -1, -1 if first < 0 || first >= filesize
122: last = range.last < 0 ? filesize + range.last : range.last
123: last = filesize - 1 if last >= filesize
124: return first, last
125: end