Class | WEBrick::HTTPServlet::DefaultFileHandler
In: | webrick/httpservlet/filehandler.rb
Parent: | AbstractServlet

### Methods

do_GET make_partial_content new not_modified? prepare_range

### Public Class methods

new(server, local_path)

[Source]

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

### Public Instance methods

do_GET(req, res)

[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)

[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)

[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_valie(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)

[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

[Validate]