Class: WEBrick::HTTPServlet::DefaultFileHandler
- Inherits:
-
AbstractServlet
- Object
- AbstractServlet
- WEBrick::HTTPServlet::DefaultFileHandler
- Defined in:
- lib/webrick/httpservlet/filehandler.rb
Overview
Servlet for serving a single file. You probably want to use the FileHandler servlet instead as it handles directories and fancy indexes.
Example:
server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
'/path/to/my_page.txt')
This servlet handles If-Modified-Since and Range requests.
Instance Method Summary collapse
-
#do_GET(req, res) ⇒ Object
:stopdoc:.
-
#initialize(server, local_path) ⇒ DefaultFileHandler
constructor
Creates a DefaultFileHandler instance for the file at
local_path
. - #make_partial_content(req, res, filename, filesize) ⇒ Object
- #not_modified?(req, res, mtime, etag) ⇒ Boolean
- #prepare_range(range, filesize) ⇒ Object
Methods inherited from AbstractServlet
#do_HEAD, #do_OPTIONS, get_instance, #service
Constructor Details
#initialize(server, local_path) ⇒ DefaultFileHandler
Creates a DefaultFileHandler instance for the file at local_path
.
37 38 39 40 |
# File 'lib/webrick/httpservlet/filehandler.rb', line 37 def initialize(server, local_path) super(server, local_path) @local_path = local_path end |
Instance Method Details
#do_GET(req, res) ⇒ Object
:stopdoc:
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/webrick/httpservlet/filehandler.rb', line 44 def do_GET(req, res) st = File::stat(@local_path) mtime = st.mtime res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i) if not_modified?(req, res, mtime, res['etag']) res.body = '' raise HTTPStatus::NotModified elsif req['range'] make_partial_content(req, res, @local_path, st.size) raise HTTPStatus::PartialContent else mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes]) res['content-type'] = mtype res['content-length'] = st.size res['last-modified'] = mtime.httpdate res.body = open(@local_path, "rb") end end |
#make_partial_content(req, res, filename, filesize) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/webrick/httpservlet/filehandler.rb', line 89 def make_partial_content(req, res, filename, filesize) mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes]) unless ranges = HTTPUtils::parse_range_header(req['range']) raise HTTPStatus::BadRequest, "Unrecognized range-spec: \"#{req['range']}\"" end open(filename, "rb"){|io| if ranges.size > 1 time = Time.now boundary = "#{time.sec}_#{time.usec}_#{Process::pid}" body = '' ranges.each{|range| first, last = prepare_range(range, filesize) next if first < 0 io.pos = first content = io.read(last-first+1) body << "--" << boundary << CRLF body << "Content-Type: #{mtype}" << CRLF body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << CRLF body << CRLF body << content body << CRLF } raise HTTPStatus::RequestRangeNotSatisfiable if body.empty? body << "--" << boundary << "--" << CRLF res["content-type"] = "multipart/byteranges; boundary=#{boundary}" res.body = body elsif range = ranges[0] first, last = prepare_range(range, filesize) raise HTTPStatus::RequestRangeNotSatisfiable if first < 0 if last == filesize - 1 content = io.dup content.pos = first else io.pos = first content = io.read(last-first+1) end res['content-type'] = mtype res['content-range'] = "bytes #{first}-#{last}/#{filesize}" res['content-length'] = last - first + 1 res.body = content else raise HTTPStatus::BadRequest end } end |
#not_modified?(req, res, mtime, etag) ⇒ Boolean
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/webrick/httpservlet/filehandler.rb', line 64 def not_modified?(req, res, mtime, etag) if ir = req['if-range'] begin if Time.httpdate(ir) >= mtime return true end rescue if HTTPUtils::split_header_value(ir).member?(res['etag']) return true end end end if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime return true end if (inm = req['if-none-match']) && HTTPUtils::split_header_value(inm).member?(res['etag']) return true end return false end |
#prepare_range(range, filesize) ⇒ Object
136 137 138 139 140 141 142 |
# File 'lib/webrick/httpservlet/filehandler.rb', line 136 def prepare_range(range, filesize) first = range.first < 0 ? filesize + range.first : range.first return -1, -1 if first < 0 || first >= filesize last = range.last < 0 ? filesize + range.last : range.last last = filesize - 1 if last >= filesize return first, last end |