Exemplo n.º 1
0
    def send_file(self, path, mimetype=None):
        """Send a local file to the browser.

        This method includes the "Last-Modified", "Content-Type" and
        "Content-Length" headers in the response, corresponding to the file
        attributes. It also checks the last modification time of the local file
        against the "If-Modified-Since" provided by the user agent, and sends a
        "304 Not Modified" response if it matches.
        """
        if not os.path.isfile(path):
            raise HTTPNotFound(_("File %(path)s not found", path=path))

        stat = os.stat(path)
        mtime = datetime.fromtimestamp(stat.st_mtime, localtz)
        last_modified = http_date(mtime)
        if last_modified == self.get_header("If-Modified-Since"):
            self.send_response(304)
            self.send_header("Content-Length", 0)
            self.end_headers()
            raise RequestDone

        if not mimetype:
            mimetype = mimetypes.guess_type(path)[0] or "application/octet-stream"

        self.send_response(200)
        self.send_header("Content-Type", mimetype)
        self.send_header("Content-Length", stat.st_size)
        self.send_header("Last-Modified", last_modified)
        self.end_headers()

        if self.method != "HEAD":
            fileobj = file(path, "rb")
            file_wrapper = self.environ.get("wsgi.file_wrapper", _FileWrapper)
            self._response = file_wrapper(fileobj, 4096)
        raise RequestDone
Exemplo n.º 2
0
    def check_modified(self, datetime, extra=""):
        """Check the request "If-None-Match" header against an entity tag.

        The entity tag is generated from the specified last modified time
        (`datetime`), optionally appending an `extra` string to
        indicate variants of the requested resource.

        That `extra` parameter can also be a list, in which case the MD5 sum
        of the list content will be used.

        If the generated tag matches the "If-None-Match" header of the request,
        this method sends a "304 Not Modified" response to the client.
        Otherwise, it adds the entity tag as an "ETag" header to the response
        so that consecutive requests can be cached.
        """
        if isinstance(extra, list):
            m = md5()
            for elt in extra:
                m.update(repr(elt))
            extra = m.hexdigest()
        etag = 'W/"%s/%s/%s"' % (self.authname, http_date(datetime), extra)
        inm = self.get_header("If-None-Match")
        if not inm or inm != etag:
            self.send_header("ETag", etag)
        else:
            self.send_response(304)
            self.send_header("Content-Length", 0)
            self.end_headers()
            raise RequestDone