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"))
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()
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
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"))
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()