class WEBrick::HTTPServlet::DefaultFileHandler

def do_GET(req, res)

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.to_s
    res['last-modified'] = mtime.httpdate
    res.body = File.open(@local_path, "rb")
  end
end

def initialize(server, local_path)

def initialize(server, local_path)
  super(server, local_path)
  @local_path = local_path
end

def make_partial_content(req, res, filename, filesize)

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
  File.open(filename, "rb"){|io|
    if ranges.size > 1
      time = Time.now
      boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
      parts = []
      ranges.each {|range|
        prange = prepare_range(range, filesize)
        next if prange[0] < 0
        parts.concat(prange)
      }
      raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
      res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
      if req.http_version < '1.1'
        res['connection'] = 'close'
      else
        res.chunked = true
      end
      res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
    elsif range = ranges[0]
      first, last = prepare_range(range, filesize)
      raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
      res['content-type'] = mtype
      res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
      res['content-length'] = (last - first + 1).to_s
      res.body = io.dup
    else
      raise HTTPStatus::BadRequest
    end
  }
end

def multipart_body(body, parts, boundary, mtype, filesize)

returns a lambda for webrick/httpresponse.rb send_body_proc
def multipart_body(body, parts, boundary, mtype, filesize)
  lambda do |socket|
    begin
      begin
        first = parts.shift
        last = parts.shift
        socket.write(
          "--#{boundary}#{CRLF}" \
          "Content-Type: #{mtype}#{CRLF}" \
          "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
          "#{CRLF}"
        )
        begin
          IO.copy_stream(body, socket, last - first + 1, first)
        rescue NotImplementedError
          body.seek(first, IO::SEEK_SET)
          IO.copy_stream(body, socket, last - first + 1)
        end
        socket.write(CRLF)
      end while parts[0]
      socket.write("--#{boundary}--#{CRLF}")
    ensure
      body.close
    end
  end
end

def not_modified?(req, res, mtime, etag)

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

def prepare_range(range, filesize)

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