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