In Files

  • webrick/httpservlet/filehandler.rb

WEBrick::HTTPServlet::DefaultFileHandler

Public Class Methods

new(server, local_path) click to toggle source
 
               # File webrick/httpservlet/filehandler.rb, line 22
def initialize(server, local_path)
  super(server, local_path)
  @local_path = local_path
end
            

Public Instance Methods

do_GET(req, res) click to toggle source
 
               # File webrick/httpservlet/filehandler.rb, line 27
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) click to toggle source
 
               # File webrick/httpservlet/filehandler.rb, line 72
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: #{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'] = "#{first}-#{last}/#{filesize}"
      res['content-length'] = last - first + 1
      res.body = content
    else
      raise HTTPStatus::BadRequest
    end
  }
end
            
not_modified?(req, res, mtime, etag) click to toggle source
 
               # File webrick/httpservlet/filehandler.rb, line 47
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) click to toggle source
 
               # File webrick/httpservlet/filehandler.rb, line 119
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
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus