We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlette/response.py`
Content:
```
1 from aiofiles.os import stat as aio_stat
2 from email.utils import formatdate
3 from mimetypes import guess_type
4 from starlette.datastructures import MutableHeaders
5 from starlette.types import Receive, Send
6 import aiofiles
7 import json
8 import hashlib
9 import os
10 import stat
11 import typing
12 
13 
14 class Response:
15     media_type = None
16     charset = "utf-8"
17 
18     def __init__(
19         self,
20         content: typing.Any,
21         status_code: int = 200,
22         headers: dict = None,
23         media_type: str = None,
24     ) -> None:
25         self.body = self.render(content)
26         self.status_code = status_code
27         if media_type is not None:
28             self.media_type = media_type
29         self.init_headers(headers)
30 
31     def render(self, content: typing.Any) -> bytes:
32         if isinstance(content, bytes):
33             return content
34         return content.encode(self.charset)
35 
36     def init_headers(self, headers):
37         if headers is None:
38             raw_headers = []
39             populate_content_length = True
40             populate_content_type = True
41         else:
42             raw_headers = [
43                 (k.lower().encode("latin-1"), v.encode("latin-1"))
44                 for k, v in headers.items()
45             ]
46             keys = [h[0] for h in raw_headers]
47             populate_content_length = b"content-length" in keys
48             populate_content_type = b"content-type" in keys
49 
50         body = getattr(self, "body", None)
51         if body is not None and populate_content_length:
52             content_length = str(len(body))
53             raw_headers.append((b"content-length", content_length.encode("latin-1")))
54 
55         content_type = self.media_type
56         if content_type is not None and populate_content_type:
57             if content_type.startswith("text/"):
58                 content_type += "; charset=" + self.charset
59             raw_headers.append((b"content-type", content_type.encode("latin-1")))
60 
61         self.raw_headers = raw_headers
62 
63     @property
64     def headers(self):
65         if not hasattr(self, "_headers"):
66             self._headers = MutableHeaders(self.raw_headers)
67         return self._headers
68 
69     async def __call__(self, receive: Receive, send: Send) -> None:
70         await send(
71             {
72                 "type": "http.response.start",
73                 "status": self.status_code,
74                 "headers": self.raw_headers,
75             }
76         )
77         await send({"type": "http.response.body", "body": self.body})
78 
79 
80 class HTMLResponse(Response):
81     media_type = "text/html"
82 
83 
84 class PlainTextResponse(Response):
85     media_type = "text/plain"
86 
87 
88 class JSONResponse(Response):
89     media_type = "application/json"
90     options = {
91         "ensure_ascii": False,
92         "allow_nan": False,
93         "indent": None,
94         "separators": (",", ":"),
95     }  # type: typing.Dict[str, typing.Any]
96 
97     def render(self, content: typing.Any) -> bytes:
98         return json.dumps(content, **self.options).encode("utf-8")
99 
100 
101 class StreamingResponse(Response):
102     def __init__(
103         self,
104         content: typing.Any,
105         status_code: int = 200,
106         headers: dict = None,
107         media_type: str = None,
108     ) -> None:
109         self.body_iterator = content
110         self.status_code = status_code
111         self.media_type = self.media_type if media_type is None else media_type
112         self.init_headers(headers)
113 
114     async def __call__(self, receive: Receive, send: Send) -> None:
115         await send(
116             {
117                 "type": "http.response.start",
118                 "status": self.status_code,
119                 "headers": self.raw_headers,
120             }
121         )
122         async for chunk in self.body_iterator:
123             if not isinstance(chunk, bytes):
124                 chunk = chunk.encode(self.charset)
125             await send({"type": "http.response.body", "body": chunk, "more_body": True})
126         await send({"type": "http.response.body", "body": b"", "more_body": False})
127 
128 
129 class FileResponse(Response):
130     chunk_size = 4096
131 
132     def __init__(
133         self,
134         path: str,
135         headers: dict = None,
136         media_type: str = None,
137         filename: str = None,
138         stat_result: os.stat_result = None,
139     ) -> None:
140         self.path = path
141         self.status_code = 200
142         self.filename = filename
143         if media_type is None:
144             media_type = guess_type(filename or path)[0] or "text/plain"
145         self.media_type = media_type
146         self.init_headers(headers)
147         if self.filename is not None:
148             content_disposition = 'attachment; filename="{}"'.format(self.filename)
149             self.headers.setdefault("content-disposition", content_disposition)
150         self.stat_result = stat_result
151         if stat_result is not None:
152             self.set_stat_headers(stat_result)
153 
154     def set_stat_headers(self, stat_result):
155         content_length = str(stat_result.st_size)
156         last_modified = formatdate(stat_result.st_mtime, usegmt=True)
157         etag_base = str(stat_result.st_mtime) + "-" + str(stat_result.st_size)
158         etag = hashlib.md5(etag_base.encode()).hexdigest()
159         self.headers.setdefault("content-length", content_length)
160         self.headers.setdefault("last-modified", last_modified)
161         self.headers.setdefault("etag", etag)
162 
163     async def __call__(self, receive: Receive, send: Send) -> None:
164         if self.stat_result is None:
165             stat_result = await aio_stat(self.path)
166             self.set_stat_headers(stat_result)
167         await send(
168             {
169                 "type": "http.response.start",
170                 "status": self.status_code,
171                 "headers": self.raw_headers,
172             }
173         )
174         async with aiofiles.open(self.path, mode="rb") as file:
175             more_body = True
176             while more_body:
177                 chunk = await file.read(self.chunk_size)
178                 more_body = len(chunk) == self.chunk_size
179                 await send(
180                     {"type": "http.response.body", "body": chunk, "more_body": False}
181                 )
182
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/starlette/response.py b/starlette/response.py
--- a/starlette/response.py
+++ b/starlette/response.py
@@ -177,5 +177,9 @@
                 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,
+                    }
                 )

{"golden_diff": "diff --git a/starlette/response.py b/starlette/response.py\n--- a/starlette/response.py\n+++ b/starlette/response.py\n@@ -177,5 +177,9 @@\n                 chunk = await file.read(self.chunk_size)\n                 more_body = len(chunk) == self.chunk_size\n                 await send(\n-                    {\"type\": \"http.response.body\", \"body\": chunk, \"more_body\": False}\n+                    {\n+                        \"type\": \"http.response.body\",\n+                        \"body\": chunk,\n+                        \"more_body\": more_body,\n+                    }\n                 )\n", "issue": "Error serving static files larger than 4096 bytes\nStatic files larger than 4096 bytes do not appear to be served correctly.\r\n\r\nHere's a test I just wrote that illustrates the problem: https://github.com/simonw/starlette/commit/e2d6665fa5c32e77a3fe22836b14620a7f5999bb\r\n\r\nRunning that test gives me the following output:\r\n\r\n```\r\n(venv) starlette $ PYTHONPATH=. pytest -k test_large_staticfile \r\n===================================================== test session starts ======================================================\r\nplatform darwin -- Python 3.6.5, pytest-3.6.1, py-1.5.3, pluggy-0.6.0\r\nrootdir: /Users/simonw/Dropbox/Development/starlette, inifile:\r\ncollected 43 items / 42 deselected                                                                                             \r\n\r\ntests/test_staticfiles.py F                                                                                              [100%]\r\n\r\n=========================================================== FAILURES ===========================================================\r\n____________________________________________________ test_large_staticfile _____________________________________________________\r\n\r\ntmpdir = local('/private/var/folders/jj/fngnv0810tn2lt_kd3911pdc0000gp/T/pytest-of-simonw/pytest-8/test_large_staticfile0')\r\n\r\n    def test_large_staticfile(tmpdir):\r\n        path = os.path.join(tmpdir, \"example.txt\")\r\n        content = \"this is a lot of content\" * 200\r\n        print(\"content len = \", len(content))\r\n        with open(path, \"w\") as file:\r\n            file.write(content)\r\n    \r\n        app = StaticFile(path=path)\r\n        client = TestClient(app)\r\n        response = client.get(\"/\")\r\n        assert response.status_code == 200\r\n>       assert len(content) == len(response.text)\r\nE       AssertionError: assert 4800 == 4096\r\nE        +  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')\r\nE        +  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')\r\nE        +    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\r\n\r\ntests/test_staticfiles.py:30: AssertionError\r\n```\n", "before_files": [{"content": "from aiofiles.os import stat as aio_stat\nfrom email.utils import formatdate\nfrom mimetypes import guess_type\nfrom starlette.datastructures import MutableHeaders\nfrom starlette.types import Receive, Send\nimport aiofiles\nimport json\nimport hashlib\nimport os\nimport stat\nimport typing\n\n\nclass Response:\n    media_type = None\n    charset = \"utf-8\"\n\n    def __init__(\n        self,\n        content: typing.Any,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n    ) -> None:\n        self.body = self.render(content)\n        self.status_code = status_code\n        if media_type is not None:\n            self.media_type = media_type\n        self.init_headers(headers)\n\n    def render(self, content: typing.Any) -> bytes:\n        if isinstance(content, bytes):\n            return content\n        return content.encode(self.charset)\n\n    def init_headers(self, headers):\n        if headers is None:\n            raw_headers = []\n            populate_content_length = True\n            populate_content_type = True\n        else:\n            raw_headers = [\n                (k.lower().encode(\"latin-1\"), v.encode(\"latin-1\"))\n                for k, v in headers.items()\n            ]\n            keys = [h[0] for h in raw_headers]\n            populate_content_length = b\"content-length\" in keys\n            populate_content_type = b\"content-type\" in keys\n\n        body = getattr(self, \"body\", None)\n        if body is not None and populate_content_length:\n            content_length = str(len(body))\n            raw_headers.append((b\"content-length\", content_length.encode(\"latin-1\")))\n\n        content_type = self.media_type\n        if content_type is not None and populate_content_type:\n            if content_type.startswith(\"text/\"):\n                content_type += \"; charset=\" + self.charset\n            raw_headers.append((b\"content-type\", content_type.encode(\"latin-1\")))\n\n        self.raw_headers = raw_headers\n\n    @property\n    def headers(self):\n        if not hasattr(self, \"_headers\"):\n            self._headers = MutableHeaders(self.raw_headers)\n        return self._headers\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        await send({\"type\": \"http.response.body\", \"body\": self.body})\n\n\nclass HTMLResponse(Response):\n    media_type = \"text/html\"\n\n\nclass PlainTextResponse(Response):\n    media_type = \"text/plain\"\n\n\nclass JSONResponse(Response):\n    media_type = \"application/json\"\n    options = {\n        \"ensure_ascii\": False,\n        \"allow_nan\": False,\n        \"indent\": None,\n        \"separators\": (\",\", \":\"),\n    }  # type: typing.Dict[str, typing.Any]\n\n    def render(self, content: typing.Any) -> bytes:\n        return json.dumps(content, **self.options).encode(\"utf-8\")\n\n\nclass StreamingResponse(Response):\n    def __init__(\n        self,\n        content: typing.Any,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n    ) -> None:\n        self.body_iterator = content\n        self.status_code = status_code\n        self.media_type = self.media_type if media_type is None else media_type\n        self.init_headers(headers)\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        async for chunk in self.body_iterator:\n            if not isinstance(chunk, bytes):\n                chunk = chunk.encode(self.charset)\n            await send({\"type\": \"http.response.body\", \"body\": chunk, \"more_body\": True})\n        await send({\"type\": \"http.response.body\", \"body\": b\"\", \"more_body\": False})\n\n\nclass FileResponse(Response):\n    chunk_size = 4096\n\n    def __init__(\n        self,\n        path: str,\n        headers: dict = None,\n        media_type: str = None,\n        filename: str = None,\n        stat_result: os.stat_result = None,\n    ) -> None:\n        self.path = path\n        self.status_code = 200\n        self.filename = filename\n        if media_type is None:\n            media_type = guess_type(filename or path)[0] or \"text/plain\"\n        self.media_type = media_type\n        self.init_headers(headers)\n        if self.filename is not None:\n            content_disposition = 'attachment; filename=\"{}\"'.format(self.filename)\n            self.headers.setdefault(\"content-disposition\", content_disposition)\n        self.stat_result = stat_result\n        if stat_result is not None:\n            self.set_stat_headers(stat_result)\n\n    def set_stat_headers(self, stat_result):\n        content_length = str(stat_result.st_size)\n        last_modified = formatdate(stat_result.st_mtime, usegmt=True)\n        etag_base = str(stat_result.st_mtime) + \"-\" + str(stat_result.st_size)\n        etag = hashlib.md5(etag_base.encode()).hexdigest()\n        self.headers.setdefault(\"content-length\", content_length)\n        self.headers.setdefault(\"last-modified\", last_modified)\n        self.headers.setdefault(\"etag\", etag)\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        if self.stat_result is None:\n            stat_result = await aio_stat(self.path)\n            self.set_stat_headers(stat_result)\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        async with aiofiles.open(self.path, mode=\"rb\") as file:\n            more_body = True\n            while more_body:\n                chunk = await file.read(self.chunk_size)\n                more_body = len(chunk) == self.chunk_size\n                await send(\n                    {\"type\": \"http.response.body\", \"body\": chunk, \"more_body\": False}\n                )\n", "path": "starlette/response.py"}], "after_files": [{"content": "from aiofiles.os import stat as aio_stat\nfrom email.utils import formatdate\nfrom mimetypes import guess_type\nfrom starlette.datastructures import MutableHeaders\nfrom starlette.types import Receive, Send\nimport aiofiles\nimport json\nimport hashlib\nimport os\nimport stat\nimport typing\n\n\nclass Response:\n    media_type = None\n    charset = \"utf-8\"\n\n    def __init__(\n        self,\n        content: typing.Any,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n    ) -> None:\n        self.body = self.render(content)\n        self.status_code = status_code\n        if media_type is not None:\n            self.media_type = media_type\n        self.init_headers(headers)\n\n    def render(self, content: typing.Any) -> bytes:\n        if isinstance(content, bytes):\n            return content\n        return content.encode(self.charset)\n\n    def init_headers(self, headers):\n        if headers is None:\n            raw_headers = []\n            populate_content_length = True\n            populate_content_type = True\n        else:\n            raw_headers = [\n                (k.lower().encode(\"latin-1\"), v.encode(\"latin-1\"))\n                for k, v in headers.items()\n            ]\n            keys = [h[0] for h in raw_headers]\n            populate_content_length = b\"content-length\" in keys\n            populate_content_type = b\"content-type\" in keys\n\n        body = getattr(self, \"body\", None)\n        if body is not None and populate_content_length:\n            content_length = str(len(body))\n            raw_headers.append((b\"content-length\", content_length.encode(\"latin-1\")))\n\n        content_type = self.media_type\n        if content_type is not None and populate_content_type:\n            if content_type.startswith(\"text/\"):\n                content_type += \"; charset=\" + self.charset\n            raw_headers.append((b\"content-type\", content_type.encode(\"latin-1\")))\n\n        self.raw_headers = raw_headers\n\n    @property\n    def headers(self):\n        if not hasattr(self, \"_headers\"):\n            self._headers = MutableHeaders(self.raw_headers)\n        return self._headers\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        await send({\"type\": \"http.response.body\", \"body\": self.body})\n\n\nclass HTMLResponse(Response):\n    media_type = \"text/html\"\n\n\nclass PlainTextResponse(Response):\n    media_type = \"text/plain\"\n\n\nclass JSONResponse(Response):\n    media_type = \"application/json\"\n    options = {\n        \"ensure_ascii\": False,\n        \"allow_nan\": False,\n        \"indent\": None,\n        \"separators\": (\",\", \":\"),\n    }  # type: typing.Dict[str, typing.Any]\n\n    def render(self, content: typing.Any) -> bytes:\n        return json.dumps(content, **self.options).encode(\"utf-8\")\n\n\nclass StreamingResponse(Response):\n    def __init__(\n        self,\n        content: typing.Any,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n    ) -> None:\n        self.body_iterator = content\n        self.status_code = status_code\n        self.media_type = self.media_type if media_type is None else media_type\n        self.init_headers(headers)\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        async for chunk in self.body_iterator:\n            if not isinstance(chunk, bytes):\n                chunk = chunk.encode(self.charset)\n            await send({\"type\": \"http.response.body\", \"body\": chunk, \"more_body\": True})\n        await send({\"type\": \"http.response.body\", \"body\": b\"\", \"more_body\": False})\n\n\nclass FileResponse(Response):\n    chunk_size = 4096\n\n    def __init__(\n        self,\n        path: str,\n        headers: dict = None,\n        media_type: str = None,\n        filename: str = None,\n        stat_result: os.stat_result = None,\n    ) -> None:\n        self.path = path\n        self.status_code = 200\n        self.filename = filename\n        if media_type is None:\n            media_type = guess_type(filename or path)[0] or \"text/plain\"\n        self.media_type = media_type\n        self.init_headers(headers)\n        if self.filename is not None:\n            content_disposition = 'attachment; filename=\"{}\"'.format(self.filename)\n            self.headers.setdefault(\"content-disposition\", content_disposition)\n        self.stat_result = stat_result\n        if stat_result is not None:\n            self.set_stat_headers(stat_result)\n\n    def set_stat_headers(self, stat_result):\n        content_length = str(stat_result.st_size)\n        last_modified = formatdate(stat_result.st_mtime, usegmt=True)\n        etag_base = str(stat_result.st_mtime) + \"-\" + str(stat_result.st_size)\n        etag = hashlib.md5(etag_base.encode()).hexdigest()\n        self.headers.setdefault(\"content-length\", content_length)\n        self.headers.setdefault(\"last-modified\", last_modified)\n        self.headers.setdefault(\"etag\", etag)\n\n    async def __call__(self, receive: Receive, send: Send) -> None:\n        if self.stat_result is None:\n            stat_result = await aio_stat(self.path)\n            self.set_stat_headers(stat_result)\n        await send(\n            {\n                \"type\": \"http.response.start\",\n                \"status\": self.status_code,\n                \"headers\": self.raw_headers,\n            }\n        )\n        async with aiofiles.open(self.path, mode=\"rb\") as file:\n            more_body = True\n            while more_body:\n                chunk = await file.read(self.chunk_size)\n                more_body = len(chunk) == self.chunk_size\n                await send(\n                    {\n                        \"type\": \"http.response.body\",\n                        \"body\": chunk,\n                        \"more_body\": more_body,\n                    }\n                )\n", "path": "starlette/response.py"}]}