Repository: encode/starlette

Issue:
Error serving static files larger than 4096 bytes
Static files larger than 4096 bytes do not appear to be served correctly.

Here's a test I just wrote that illustrates the problem: https://github.com/simonw/starlette/commit/e2d6665fa5c32e77a3fe22836b14620a7f5999bb

Running that test gives me the following output:

```
(venv) starlette $ PYTHONPATH=. pytest -k test_large_staticfile 
===================================================== test session starts ======================================================
platform darwin -- Python 3.6.5, pytest-3.6.1, py-1.5.3, pluggy-0.6.0
rootdir: /Users/simonw/Dropbox/Development/starlette, inifile:
collected 43 items / 42 deselected                                                                                             

tests/test_staticfiles.py F                                                                                              [100%]

=========================================================== FAILURES ===========================================================
____________________________________________________ test_large_staticfile _____________________________________________________

tmpdir = local('/private/var/folders/jj/fngnv0810tn2lt_kd3911pdc0000gp/T/pytest-of-simonw/pytest-8/test_large_staticfile0')

    def test_large_staticfile(tmpdir):
        path = os.path.join(tmpdir, "example.txt")
        content = "this is a lot of content" * 200
        print("content len = ", len(content))
        with open(path, "w") as file:
            file.write(content)
    
        app = StaticFile(path=path)
        client = TestClient(app)
        response = client.get("/")
        assert response.status_code == 200
>       assert len(content) == len(response.text)
E       AssertionError: assert 4800 == 4096
E        +  where 4800 = len('this is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of cont...is is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of content')
E        +  and   4096 = len(' contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot...ontentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of')
E        +    where ' contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot...ontentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of contentthis is a lot of' = <Response [200]>.text

tests/test_staticfiles.py:30: AssertionError
```


Discussion:

Resolving patch:
diff --git a/starlette/response.py b/starlette/response.py
--- a/starlette/response.py
+++ b/starlette/response.py
@@ -177,5 +177,9 @@ async def __call__(self, receive: Receive, send: Send) -> None:
                 chunk = await file.read(self.chunk_size)
                 more_body = len(chunk) == self.chunk_size
                 await send(
-                    {"type": "http.response.body", "body": chunk, "more_body": False}
+                    {
+                        "type": "http.response.body",
+                        "body": chunk,
+                        "more_body": more_body,
+                    }
                 )


Test patch:
diff --git a/tests/test_response.py b/tests/test_response.py
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -70,8 +70,9 @@ async def asgi(receive, send):
 
 def test_file_response(tmpdir):
     path = os.path.join(tmpdir, "xyz")
+    content = b"<file content>" * 1000
     with open(path, "wb") as file:
-        file.write(b"<file content>")
+        file.write(content)
 
     def app(scope):
         return FileResponse(path=path, filename="example.png")
@@ -80,7 +81,7 @@ def app(scope):
     response = client.get("/")
     expected_disposition = 'attachment; filename="example.png"'
     assert response.status_code == 200
-    assert response.content == b"<file content>"
+    assert response.content == content
     assert response.headers["content-type"] == "image/png"
     assert response.headers["content-disposition"] == expected_disposition
     assert "content-length" in response.headers
diff --git a/tests/test_staticfiles.py b/tests/test_staticfiles.py
--- a/tests/test_staticfiles.py
+++ b/tests/test_staticfiles.py
@@ -16,6 +16,21 @@ def test_staticfile(tmpdir):
     assert response.text == "<file content>"
 
 
+def test_large_staticfile(tmpdir):
+    path = os.path.join(tmpdir, "example.txt")
+    content = "this is a lot of content" * 200
+    print("content len = ", len(content))
+    with open(path, "w") as file:
+        file.write(content)
+
+    app = StaticFile(path=path)
+    client = TestClient(app)
+    response = client.get("/")
+    assert response.status_code == 200
+    assert len(content) == len(response.text)
+    assert content == response.text
+
+
 def test_staticfile_post(tmpdir):
     path = os.path.join(tmpdir, "example.txt")
     with open(path, "w") as file: