コード例 #1
0
ファイル: http_response.py プロジェクト: AmesianX/skitai
 def File(self, path, mimetype='application/octet-stream', filename=None):
     self.set_header('Content-Type', mimetype)
     self.set_header('Content-Length', str(os.path.getsize(path)))
     if filename:
         self.set_header('Content-Disposition',
                         'attachment; filename="{}"'.format(filename))
     return producers.file_producer(open(path, "rb"))
コード例 #2
0
ファイル: default_handler.py プロジェクト: hansroh/skitai
    def handle_request(self, request):
        if request.command not in ('get', 'head'):
            self.handle_alternative(request)
            return

        path, params, query, fragment = request.split_uri()
        if '%' in path:
            path = unquote(path)

        # return redirect
        if path == "":
            request.response['Location'] = '/'
            request.response.error(301)
            return

        if path.find("./") != -1 or path.find("//") != -1:
            request.response.error(404)
            return

        while path and path[0] == '/':
            path = path[1:]

        if self.filesystem.isdir(path):
            if path and path[-1] != '/':
                request.response['Location'] = '/%s/' % path
                request.response.error(301)
                return

            found = False
            for default in self.directory_defaults:
                p = path + default
                if self.filesystem.isfile(p):
                    path = p
                    found = True
                    break

            if not found:
                self.handle_alternative(request)
                return

        elif not self.filesystem.isfile(path):
            return self.handle_alternative(request)

        if path and path[-1] == "/":
            return request.response.error(404)

        if self.isprohibited(request, path):
            return

        try:
            current_stat = self.filesystem.stat(path)
            mtime = current_stat[stat.ST_MTIME]
            file_length = current_stat[stat.ST_SIZE]
        except:
            self.handle_alternative(request)
            return

        etag = self.make_etag(file_length, mtime)
        if self.is_etag_matched(request, 'if-none-match',
                                etag) == 'matched' or self.is_modified(
                                    request, "if-modified-since", mtime,
                                    file_length) == 'unmodified':
            self.set_cache_control(request, path, mtime, etag)
            request.response.start(304)
            request.response.done()
            return

        if self.is_etag_matched(request, 'if-match',
                                etag) == 'unmatched' or self.is_modified(
                                    request, "if-unmodified-since", mtime,
                                    file_length) == 'modified':
            request.response.start(412)
            request.response.done()
            return

        range_ = request.get_header('range')
        if range_:
            if self.is_etag_matched(request, 'if-range', etag) == 'unmatched':
                range_ = None  # ignore range
            else:
                try:
                    rg_start, rg_end = self.parse_range(range_, file_length)
                except:
                    request.response.start(416)
                    request.response.done()
                    return

        self.set_cache_control(request, path, mtime, etag)
        self.set_content_type(path, request)

        if range_:
            request.response['Content-Range'] = 'bytes {}-{}/{}'.format(
                rg_start, rg_end, file_length)
            request.response['Content-Length'] = (rg_end - rg_start) + 1
            offset, limit = rg_start, (rg_end - rg_start) + 1
            request.response.start(206)

        else:
            request.response['Content-Length'] = file_length
            offset, limit = 0, file_length

        if request.command == 'get' and limit:
            # if head, don't send contents
            if file_length < 4096:
                request.response.push(
                    self.memcache.read(path, self.filesystem.translate(path),
                                       etag)[offset:limit])
            else:
                request.response.push(
                    producers.file_producer(self.filesystem.open(path, 'rb'),
                                            proxsize=file_length,
                                            offset=offset,
                                            limit=limit))
        request.response.done()
コード例 #3
0
ファイル: test_http_response.py プロジェクト: AmesianX/skitai
def test_producers(client):
    def g():
        for i in range(10):
            yield ("A" * 10).encode("utf8")

    def l():
        return ([("A" * 10).encode("utf8")] * 10)

    class s:
        def __init__(self):
            self.d = list(range(10))
            self.closed = 0

        def close(self):
            self.closed = 1

        def read(self, size):
            if not self.d:
                return b""
            self.d.pop()
            return ("A" * size).encode("utf8")

    response = make_response(client)
    jpg = open(os.path.join(confutil.getroot(), "statics", "reindeer.jpg"),
               "rb")
    response("200 OK",
             "",
             headers=[("Content-Type", "application/octet-stream")])
    response.push_and_done(producers.file_producer(jpg))
    assert response.get("content-encoding") is None
    assert response.get("transfer-encoding") == "chunked"
    assert jpg.closed

    response = make_response(client)
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    response.push_and_done(producers.iter_producer(g()))
    assert response.get("content-encoding") == "gzip"
    assert response.get("transfer-encoding") == "chunked"

    response = make_response(client)
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    response.push_and_done(producers.list_producer(l()))
    assert response.get("content-encoding") is None
    assert response.get("transfer-encoding") == "chunked"

    response = make_response(client)
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    producer = s()
    response.push_and_done(producers.closing_stream_producer(producer))
    assert response.get("content-encoding") == "gzip"
    assert response.get("transfer-encoding") == "chunked"
    assert producer.closed

    response = make_response(client)
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    jpg = open(os.path.join(confutil.getroot(), "statics", "reindeer.jpg"),
               "rb")
    response.push(producers.closing_stream_producer(s()))
    response.push(producers.list_producer(l()))
    response.push(producers.iter_producer(g()))
    response.push(producers.file_producer(jpg))
    response.done()

    assert response.get("content-encoding") == "gzip"
    assert response.get("transfer-encoding") == "chunked"
    assert producer.closed
    assert jpg.closed

    response = make_response(client)
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    jpg = open(os.path.join(confutil.getroot(), "statics", "reindeer.jpg"),
               "rb")
    response.push(producers.closing_stream_producer(s()))
    response.push(producers.list_producer(l()))
    response.push(producers.iter_producer(g()))
    response.push(producers.file_producer(jpg))
    response.done()

    response = make_response(client, version="2.0")
    response("200 OK", "", headers=[("Content-Type", "text/html")])
    jpg = open(os.path.join(confutil.getroot(), "statics", "reindeer.jpg"),
               "rb")
    conn = MagicMock()
    conn.data_to_send.return_value = jpg.read()
    p = h2frame_producer(1, 0, 1, producers.file_producer(jpg), conn,
                         threading.Lock())
    response.push_and_done(p)
    assert response.get("content-encoding") is None
    rprint(response.reply_headers)
    assert response.get("transfer-encoding") is None
コード例 #4
0
 def fstream(self, path, mimetype='application/octet-stream'):
     self.response.set_header('Content-Type', mimetype)
     self.response.set_header('Content-Length', str(os.path.getsize(path)))
     return file_producer(open(path, "rb"))
コード例 #5
0
ファイル: default_handler.py プロジェクト: AmesianX/skitai
    def handle_request(self, request):
        if request.command not in ('get', 'head'):
            self.handle_alternative(request)
            return

        path, params, query, fragment = request.split_uri()
        if '%' in path:
            path = unquote(path)

        # return redirect
        if path == "":
            request.response['Location'] = '/'
            request.response.error(301)
            return

        if path.find("./") != -1 or path.find("//") != -1:
            request.response.error(404)
            return

        while path and path[0] == '/':
            path = path[1:]

        if self.filesystem.isdir(path):
            if path and path[-1] != '/':
                request.response['Location'] = '/%s/' % path
                request.response.error(301)
                return

            found = False
            for default in self.directory_defaults:
                p = path + default
                if self.filesystem.isfile(p):
                    path = p
                    found = True
                    break

            if not found:
                self.handle_alternative(request)
                return

        elif not self.filesystem.isfile(path):
            return self.handle_alternative(request)

        if path and path[-1] == "/":
            return request.response.error(404)

        if self.isprohibited(request, path):
            return

        try:
            current_stat = self.filesystem.stat(path)
            mtime = current_stat[stat.ST_MTIME]
            file_length = current_stat[stat.ST_SIZE]
        except:
            self.handle_alternative(request)
            return

        etag = self.make_etag(file_length, mtime)
        inm_h = request.get_header("if-none-match")
        if inm_h:
            inm = get_re_match(IF_NONE_MATCH, inm_h)
            if inm and etag == inm.group(1):
                self.set_cache_control(request, path, mtime, etag)
                request.response.start(304)
                request.response.done()
                return

        ims_h = request.get_header("if-modified-since")
        if ims_h:
            ims = get_re_match(IF_MODIFIED_SINCE, ims_h)
            length_match = 1
            if ims:
                length = ims.group(4)
                if length:
                    try:
                        length = int(length)
                        if length != file_length:
                            length_match = 0
                    except:
                        pass

            ims_date = 0
            if ims:
                ims_date = http_date.parse_http_date(ims.group(1))

            if length_match and ims_date:
                if mtime <= ims_date:
                    self.set_cache_control(request, path, mtime, etag)
                    request.response.start(304)
                    request.response.done()
                return

        request.response['Content-Length'] = file_length
        self.set_cache_control(request, path, mtime, etag)
        self.set_content_type(path, request)

        if request.command == 'get':
            # if head, don't send contents
            if file_length < 4096:
                request.response.push(
                    self.memcache.read(path, self.filesystem.translate(path),
                                       etag))
            else:
                request.response.push(
                    producers.file_producer(self.filesystem.open(path, 'rb'),
                                            proxsize=file_length))
        request.response.done()