We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support for background tasks for `GraphQLApp`
Since Response provided by starlette take a background argument, Any plans to add support for running a list of background tasks after the response has been sent in the case of `GraphQLApp`?

A naive implementation looks like this

```python
class Holder(object):
    def __init__(self):
        self._list = []

    def add(self, function, *args, **kwargs):
        func = functools.partial(function, *args, **kwargs)
        self._list.append(func)

    def clean(self):
        self._list = []

    def run_all_tasks(self):
        for i in self._list:
            i()
```

```python
class EnhancedGraphqlApp(GraphQLApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.holder = Holder()
        
    async def execute(self, query, variables=None, operation_name=None):  # type: ignore
        print("Started")
        print(self.holder._list)
        if self.is_async:
            result = await self.schema.execute(
                query,
                variables=variables,
                operation_name=operation_name,
                context={"holder": self.holder},
                executor=self.executor,
                return_promise=True,
            )
        else:
            func = functools.partial(
                self.schema.execute,
                context={"holder": self.holder},
                variables=variables,
                operation_name=operation_name,
            )
            loop = asyncio.get_event_loop()
            result = await loop.run_in_executor(None, func, query)
        return result

    def run_tasks(self):
        for i in self.holder._list:
            i()
        self.holder.clean()

    async def handle_graphql(self, request: Request) -> Response:
        # existing implementation
        ... 
        tasks = BackgroundTask(self.run_tasks)
        return JSONResponse(response_data, background=tasks, status_code=status_code)
```

And usage in the Schema class would be just like how context is used generally

```python
def hello(name):
    print(f"My name is {name}")

class Query(object):
    hello = graphene.String(name=graphene.String(default_value="stranger"))
    alls = graphene.List(AllModel)

    async def resolve_alls(self, info):
        rresult = await async_print_all_models()
        holder = info.context.get('holder')
        holder.add(hello,"James")
        return [AllModel(name=x.name) for x in rresult]
```

--- 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/background.py`
Content:
```
1 import asyncio
2 import typing
3 
4 from starlette.concurrency import run_in_threadpool
5 
6 
7 class BackgroundTask:
8     def __init__(
9         self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any
10     ) -> None:
11         self.func = func
12         self.args = args
13         self.kwargs = kwargs
14         self.is_async = asyncio.iscoroutinefunction(func)
15 
16     async def __call__(self) -> None:
17         if self.is_async:
18             await self.func(*self.args, **self.kwargs)
19         else:
20             await run_in_threadpool(self.func, *self.args, **self.kwargs)
21
```

Path: `starlette/graphql.py`
Content:
```
1 import functools
2 import json
3 import typing
4 
5 from starlette import status
6 from starlette.concurrency import run_in_threadpool
7 from starlette.requests import Request
8 from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response
9 from starlette.types import ASGIInstance, Receive, Scope, Send
10 
11 try:
12     import graphene
13     from graphql.execution.executors.asyncio import AsyncioExecutor
14     from graphql.error import format_error as format_graphql_error
15     from graphql.error import GraphQLError
16 except ImportError:  # pragma: nocover
17     graphene = None  # type: ignore
18     AsyncioExecutor = None  # type: ignore
19     format_graphql_error = None  # type: ignore
20     GraphQLError = None  # type: ignore
21 
22 
23 class GraphQLApp:
24     def __init__(self, schema: "graphene.Schema", executor: typing.Any = None) -> None:
25         self.schema = schema
26         self.executor = executor
27         self.is_async = isinstance(executor, AsyncioExecutor)
28 
29     def __call__(self, scope: Scope) -> ASGIInstance:
30         return functools.partial(self.asgi, scope=scope)
31 
32     async def asgi(self, receive: Receive, send: Send, scope: Scope) -> None:
33         request = Request(scope, receive=receive)
34         response = await self.handle_graphql(request)
35         await response(receive, send)
36 
37     async def handle_graphql(self, request: Request) -> Response:
38         if request.method == "GET":
39             if "text/html" in request.headers.get("Accept", ""):
40                 return await self.handle_graphiql(request)
41 
42             data = request.query_params  # type: typing.Mapping[str, typing.Any]
43 
44         elif request.method == "POST":
45             content_type = request.headers.get("Content-Type", "")
46 
47             if "application/json" in content_type:
48                 data = await request.json()
49             elif "application/graphql" in content_type:
50                 body = await request.body()
51                 text = body.decode()
52                 data = {"query": text}
53             elif "query" in request.query_params:
54                 data = request.query_params
55             else:
56                 return PlainTextResponse(
57                     "Unsupported Media Type",
58                     status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
59                 )
60 
61         else:
62             return PlainTextResponse(
63                 "Method Not Allowed", status_code=status.HTTP_405_METHOD_NOT_ALLOWED
64             )
65 
66         try:
67             query = data["query"]
68             variables = data.get("variables")
69             operation_name = data.get("operationName")
70         except KeyError:
71             return PlainTextResponse(
72                 "No GraphQL query found in the request",
73                 status_code=status.HTTP_400_BAD_REQUEST,
74             )
75 
76         result = await self.execute(request, query, variables)
77         error_data = (
78             [format_graphql_error(err) for err in result.errors]
79             if result.errors
80             else None
81         )
82         response_data = {"data": result.data, "errors": error_data}
83         status_code = (
84             status.HTTP_400_BAD_REQUEST if result.errors else status.HTTP_200_OK
85         )
86         return JSONResponse(response_data, status_code=status_code)
87 
88     async def execute(  # type: ignore
89         self, request, query, variables=None, operation_name=None
90     ):
91         context = dict(request=request)
92 
93         if self.is_async:
94             return await self.schema.execute(
95                 query,
96                 variables=variables,
97                 operation_name=operation_name,
98                 executor=self.executor,
99                 return_promise=True,
100                 context=context,
101             )
102         else:
103             return await run_in_threadpool(
104                 self.schema.execute,
105                 query,
106                 variables=variables,
107                 operation_name=operation_name,
108                 context=context,
109             )
110 
111     async def handle_graphiql(self, request: Request) -> Response:
112         text = GRAPHIQL.replace("{{REQUEST_PATH}}", json.dumps(request.url.path))
113         return HTMLResponse(text)
114 
115 
116 GRAPHIQL = """
117 <!--
118  *  Copyright (c) Facebook, Inc.
119  *  All rights reserved.
120  *
121  *  This source code is licensed under the license found in the
122  *  LICENSE file in the root directory of this source tree.
123 -->
124 <!DOCTYPE html>
125 <html>
126   <head>
127     <style>
128       body {
129         height: 100%;
130         margin: 0;
131         width: 100%;
132         overflow: hidden;
133       }
134       #graphiql {
135         height: 100vh;
136       }
137     </style>
138     <!--
139       This GraphiQL example depends on Promise and fetch, which are available in
140       modern browsers, but can be "polyfilled" for older browsers.
141       GraphiQL itself depends on React DOM.
142       If you do not want to rely on a CDN, you can host these files locally or
143       include them directly in your favored resource bunder.
144     -->
145     <link href="//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.css" rel="stylesheet"/>
146     <script src="//cdn.jsdelivr.net/npm/whatwg-fetch@2.0.3/fetch.min.js"></script>
147     <script src="//cdn.jsdelivr.net/npm/react@16.2.0/umd/react.production.min.js"></script>
148     <script src="//cdn.jsdelivr.net/npm/react-dom@16.2.0/umd/react-dom.production.min.js"></script>
149     <script src="//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.min.js"></script>
150   </head>
151   <body>
152     <div id="graphiql">Loading...</div>
153     <script>
154       /**
155        * This GraphiQL example illustrates how to use some of GraphiQL's props
156        * in order to enable reading and updating the URL parameters, making
157        * link sharing of queries a little bit easier.
158        *
159        * This is only one example of this kind of feature, GraphiQL exposes
160        * various React params to enable interesting integrations.
161        */
162       // Parse the search string to get url parameters.
163       var search = window.location.search;
164       var parameters = {};
165       search.substr(1).split('&').forEach(function (entry) {
166         var eq = entry.indexOf('=');
167         if (eq >= 0) {
168           parameters[decodeURIComponent(entry.slice(0, eq))] =
169             decodeURIComponent(entry.slice(eq + 1));
170         }
171       });
172       // if variables was provided, try to format it.
173       if (parameters.variables) {
174         try {
175           parameters.variables =
176             JSON.stringify(JSON.parse(parameters.variables), null, 2);
177         } catch (e) {
178           // Do nothing, we want to display the invalid JSON as a string, rather
179           // than present an error.
180         }
181       }
182       // When the query and variables string is edited, update the URL bar so
183       // that it can be easily shared
184       function onEditQuery(newQuery) {
185         parameters.query = newQuery;
186         updateURL();
187       }
188       function onEditVariables(newVariables) {
189         parameters.variables = newVariables;
190         updateURL();
191       }
192       function onEditOperationName(newOperationName) {
193         parameters.operationName = newOperationName;
194         updateURL();
195       }
196       function updateURL() {
197         var newSearch = '?' + Object.keys(parameters).filter(function (key) {
198           return Boolean(parameters[key]);
199         }).map(function (key) {
200           return encodeURIComponent(key) + '=' +
201             encodeURIComponent(parameters[key]);
202         }).join('&');
203         history.replaceState(null, null, newSearch);
204       }
205       // Defines a GraphQL fetcher using the fetch API. You're not required to
206       // use fetch, and could instead implement graphQLFetcher however you like,
207       // as long as it returns a Promise or Observable.
208       function graphQLFetcher(graphQLParams) {
209         // This example expects a GraphQL server at the path /graphql.
210         // Change this to point wherever you host your GraphQL server.
211         return fetch({{REQUEST_PATH}}, {
212           method: 'post',
213           headers: {
214             'Accept': 'application/json',
215             'Content-Type': 'application/json',
216           },
217           body: JSON.stringify(graphQLParams),
218           credentials: 'include',
219         }).then(function (response) {
220           return response.text();
221         }).then(function (responseBody) {
222           try {
223             return JSON.parse(responseBody);
224           } catch (error) {
225             return responseBody;
226           }
227         });
228       }
229       // Render <GraphiQL /> into the body.
230       // See the README in the top level of this module to learn more about
231       // how you can customize GraphiQL by providing different values or
232       // additional child elements.
233       ReactDOM.render(
234         React.createElement(GraphiQL, {
235           fetcher: graphQLFetcher,
236           query: parameters.query,
237           variables: parameters.variables,
238           operationName: parameters.operationName,
239           onEditQuery: onEditQuery,
240           onEditVariables: onEditVariables,
241           onEditOperationName: onEditOperationName
242         }),
243         document.getElementById('graphiql')
244       );
245     </script>
246   </body>
247 </html>
248 """
249
```
--- 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/background.py b/starlette/background.py
--- a/starlette/background.py
+++ b/starlette/background.py
@@ -18,3 +18,18 @@
             await self.func(*self.args, **self.kwargs)
         else:
             await run_in_threadpool(self.func, *self.args, **self.kwargs)
+
+
+class BackgroundTasks(BackgroundTask):
+    def __init__(self, tasks: typing.Sequence[BackgroundTask] = []):
+        self.tasks = list(tasks)
+
+    def add_task(
+        self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any
+    ) -> None:
+        task = BackgroundTask(func, *args, **kwargs)
+        self.tasks.append(task)
+
+    async def __call__(self) -> None:
+        for task in self.tasks:
+            await task()
diff --git a/starlette/graphql.py b/starlette/graphql.py
--- a/starlette/graphql.py
+++ b/starlette/graphql.py
@@ -3,6 +3,7 @@
 import typing
 
 from starlette import status
+from starlette.background import BackgroundTasks
 from starlette.concurrency import run_in_threadpool
 from starlette.requests import Request
 from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response
@@ -73,7 +74,10 @@
                 status_code=status.HTTP_400_BAD_REQUEST,
             )
 
-        result = await self.execute(request, query, variables)
+        background = BackgroundTasks()
+        context = {"request": request, "background": background}
+
+        result = await self.execute(query, variables=variables, context=context)
         error_data = (
             [format_graphql_error(err) for err in result.errors]
             if result.errors
@@ -83,13 +87,14 @@
         status_code = (
             status.HTTP_400_BAD_REQUEST if result.errors else status.HTTP_200_OK
         )
-        return JSONResponse(response_data, status_code=status_code)
+
+        return JSONResponse(
+            response_data, status_code=status_code, background=background
+        )
 
     async def execute(  # type: ignore
-        self, request, query, variables=None, operation_name=None
+        self, query, variables=None, context=None, operation_name=None
     ):
-        context = dict(request=request)
-
         if self.is_async:
             return await self.schema.execute(
                 query,

{"golden_diff": "diff --git a/starlette/background.py b/starlette/background.py\n--- a/starlette/background.py\n+++ b/starlette/background.py\n@@ -18,3 +18,18 @@\n             await self.func(*self.args, **self.kwargs)\n         else:\n             await run_in_threadpool(self.func, *self.args, **self.kwargs)\n+\n+\n+class BackgroundTasks(BackgroundTask):\n+    def __init__(self, tasks: typing.Sequence[BackgroundTask] = []):\n+        self.tasks = list(tasks)\n+\n+    def add_task(\n+        self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any\n+    ) -> None:\n+        task = BackgroundTask(func, *args, **kwargs)\n+        self.tasks.append(task)\n+\n+    async def __call__(self) -> None:\n+        for task in self.tasks:\n+            await task()\ndiff --git a/starlette/graphql.py b/starlette/graphql.py\n--- a/starlette/graphql.py\n+++ b/starlette/graphql.py\n@@ -3,6 +3,7 @@\n import typing\n \n from starlette import status\n+from starlette.background import BackgroundTasks\n from starlette.concurrency import run_in_threadpool\n from starlette.requests import Request\n from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response\n@@ -73,7 +74,10 @@\n                 status_code=status.HTTP_400_BAD_REQUEST,\n             )\n \n-        result = await self.execute(request, query, variables)\n+        background = BackgroundTasks()\n+        context = {\"request\": request, \"background\": background}\n+\n+        result = await self.execute(query, variables=variables, context=context)\n         error_data = (\n             [format_graphql_error(err) for err in result.errors]\n             if result.errors\n@@ -83,13 +87,14 @@\n         status_code = (\n             status.HTTP_400_BAD_REQUEST if result.errors else status.HTTP_200_OK\n         )\n-        return JSONResponse(response_data, status_code=status_code)\n+\n+        return JSONResponse(\n+            response_data, status_code=status_code, background=background\n+        )\n \n     async def execute(  # type: ignore\n-        self, request, query, variables=None, operation_name=None\n+        self, query, variables=None, context=None, operation_name=None\n     ):\n-        context = dict(request=request)\n-\n         if self.is_async:\n             return await self.schema.execute(\n                 query,\n", "issue": "Support for background tasks for `GraphQLApp`\nSince Response provided by starlette take a background argument, Any plans to add support for running a list of background tasks after the response has been sent in the case of `GraphQLApp`?\r\n\r\nA naive implementation looks like this\r\n\r\n```python\r\nclass Holder(object):\r\n    def __init__(self):\r\n        self._list = []\r\n\r\n    def add(self, function, *args, **kwargs):\r\n        func = functools.partial(function, *args, **kwargs)\r\n        self._list.append(func)\r\n\r\n    def clean(self):\r\n        self._list = []\r\n\r\n    def run_all_tasks(self):\r\n        for i in self._list:\r\n            i()\r\n```\r\n\r\n```python\r\nclass EnhancedGraphqlApp(GraphQLApp):\r\n    def __init__(self, **kwargs):\r\n        super().__init__(**kwargs)\r\n        self.holder = Holder()\r\n        \r\n    async def execute(self, query, variables=None, operation_name=None):  # type: ignore\r\n        print(\"Started\")\r\n        print(self.holder._list)\r\n        if self.is_async:\r\n            result = await self.schema.execute(\r\n                query,\r\n                variables=variables,\r\n                operation_name=operation_name,\r\n                context={\"holder\": self.holder},\r\n                executor=self.executor,\r\n                return_promise=True,\r\n            )\r\n        else:\r\n            func = functools.partial(\r\n                self.schema.execute,\r\n                context={\"holder\": self.holder},\r\n                variables=variables,\r\n                operation_name=operation_name,\r\n            )\r\n            loop = asyncio.get_event_loop()\r\n            result = await loop.run_in_executor(None, func, query)\r\n        return result\r\n\r\n    def run_tasks(self):\r\n        for i in self.holder._list:\r\n            i()\r\n        self.holder.clean()\r\n\r\n    async def handle_graphql(self, request: Request) -> Response:\r\n        # existing implementation\r\n        ... \r\n        tasks = BackgroundTask(self.run_tasks)\r\n        return JSONResponse(response_data, background=tasks, status_code=status_code)\r\n```\r\n\r\nAnd usage in the Schema class would be just like how context is used generally\r\n\r\n```python\r\ndef hello(name):\r\n    print(f\"My name is {name}\")\r\n\r\nclass Query(object):\r\n    hello = graphene.String(name=graphene.String(default_value=\"stranger\"))\r\n    alls = graphene.List(AllModel)\r\n\r\n    async def resolve_alls(self, info):\r\n        rresult = await async_print_all_models()\r\n        holder = info.context.get('holder')\r\n        holder.add(hello,\"James\")\r\n        return [AllModel(name=x.name) for x in rresult]\r\n```\n", "before_files": [{"content": "import asyncio\nimport typing\n\nfrom starlette.concurrency import run_in_threadpool\n\n\nclass BackgroundTask:\n    def __init__(\n        self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any\n    ) -> None:\n        self.func = func\n        self.args = args\n        self.kwargs = kwargs\n        self.is_async = asyncio.iscoroutinefunction(func)\n\n    async def __call__(self) -> None:\n        if self.is_async:\n            await self.func(*self.args, **self.kwargs)\n        else:\n            await run_in_threadpool(self.func, *self.args, **self.kwargs)\n", "path": "starlette/background.py"}, {"content": "import functools\nimport json\nimport typing\n\nfrom starlette import status\nfrom starlette.concurrency import run_in_threadpool\nfrom starlette.requests import Request\nfrom starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response\nfrom starlette.types import ASGIInstance, Receive, Scope, Send\n\ntry:\n    import graphene\n    from graphql.execution.executors.asyncio import AsyncioExecutor\n    from graphql.error import format_error as format_graphql_error\n    from graphql.error import GraphQLError\nexcept ImportError:  # pragma: nocover\n    graphene = None  # type: ignore\n    AsyncioExecutor = None  # type: ignore\n    format_graphql_error = None  # type: ignore\n    GraphQLError = None  # type: ignore\n\n\nclass GraphQLApp:\n    def __init__(self, schema: \"graphene.Schema\", executor: typing.Any = None) -> None:\n        self.schema = schema\n        self.executor = executor\n        self.is_async = isinstance(executor, AsyncioExecutor)\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return functools.partial(self.asgi, scope=scope)\n\n    async def asgi(self, receive: Receive, send: Send, scope: Scope) -> None:\n        request = Request(scope, receive=receive)\n        response = await self.handle_graphql(request)\n        await response(receive, send)\n\n    async def handle_graphql(self, request: Request) -> Response:\n        if request.method == \"GET\":\n            if \"text/html\" in request.headers.get(\"Accept\", \"\"):\n                return await self.handle_graphiql(request)\n\n            data = request.query_params  # type: typing.Mapping[str, typing.Any]\n\n        elif request.method == \"POST\":\n            content_type = request.headers.get(\"Content-Type\", \"\")\n\n            if \"application/json\" in content_type:\n                data = await request.json()\n            elif \"application/graphql\" in content_type:\n                body = await request.body()\n                text = body.decode()\n                data = {\"query\": text}\n            elif \"query\" in request.query_params:\n                data = request.query_params\n            else:\n                return PlainTextResponse(\n                    \"Unsupported Media Type\",\n                    status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,\n                )\n\n        else:\n            return PlainTextResponse(\n                \"Method Not Allowed\", status_code=status.HTTP_405_METHOD_NOT_ALLOWED\n            )\n\n        try:\n            query = data[\"query\"]\n            variables = data.get(\"variables\")\n            operation_name = data.get(\"operationName\")\n        except KeyError:\n            return PlainTextResponse(\n                \"No GraphQL query found in the request\",\n                status_code=status.HTTP_400_BAD_REQUEST,\n            )\n\n        result = await self.execute(request, query, variables)\n        error_data = (\n            [format_graphql_error(err) for err in result.errors]\n            if result.errors\n            else None\n        )\n        response_data = {\"data\": result.data, \"errors\": error_data}\n        status_code = (\n            status.HTTP_400_BAD_REQUEST if result.errors else status.HTTP_200_OK\n        )\n        return JSONResponse(response_data, status_code=status_code)\n\n    async def execute(  # type: ignore\n        self, request, query, variables=None, operation_name=None\n    ):\n        context = dict(request=request)\n\n        if self.is_async:\n            return await self.schema.execute(\n                query,\n                variables=variables,\n                operation_name=operation_name,\n                executor=self.executor,\n                return_promise=True,\n                context=context,\n            )\n        else:\n            return await run_in_threadpool(\n                self.schema.execute,\n                query,\n                variables=variables,\n                operation_name=operation_name,\n                context=context,\n            )\n\n    async def handle_graphiql(self, request: Request) -> Response:\n        text = GRAPHIQL.replace(\"{{REQUEST_PATH}}\", json.dumps(request.url.path))\n        return HTMLResponse(text)\n\n\nGRAPHIQL = \"\"\"\n<!--\n *  Copyright (c) Facebook, Inc.\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n      #graphiql {\n        height: 100vh;\n      }\n    </style>\n    <!--\n      This GraphiQL example depends on Promise and fetch, which are available in\n      modern browsers, but can be \"polyfilled\" for older browsers.\n      GraphiQL itself depends on React DOM.\n      If you do not want to rely on a CDN, you can host these files locally or\n      include them directly in your favored resource bunder.\n    -->\n    <link href=\"//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.css\" rel=\"stylesheet\"/>\n    <script src=\"//cdn.jsdelivr.net/npm/whatwg-fetch@2.0.3/fetch.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/react@16.2.0/umd/react.production.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/react-dom@16.2.0/umd/react-dom.production.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"graphiql\">Loading...</div>\n    <script>\n      /**\n       * This GraphiQL example illustrates how to use some of GraphiQL's props\n       * in order to enable reading and updating the URL parameters, making\n       * link sharing of queries a little bit easier.\n       *\n       * This is only one example of this kind of feature, GraphiQL exposes\n       * various React params to enable interesting integrations.\n       */\n      // Parse the search string to get url parameters.\n      var search = window.location.search;\n      var parameters = {};\n      search.substr(1).split('&').forEach(function (entry) {\n        var eq = entry.indexOf('=');\n        if (eq >= 0) {\n          parameters[decodeURIComponent(entry.slice(0, eq))] =\n            decodeURIComponent(entry.slice(eq + 1));\n        }\n      });\n      // if variables was provided, try to format it.\n      if (parameters.variables) {\n        try {\n          parameters.variables =\n            JSON.stringify(JSON.parse(parameters.variables), null, 2);\n        } catch (e) {\n          // Do nothing, we want to display the invalid JSON as a string, rather\n          // than present an error.\n        }\n      }\n      // When the query and variables string is edited, update the URL bar so\n      // that it can be easily shared\n      function onEditQuery(newQuery) {\n        parameters.query = newQuery;\n        updateURL();\n      }\n      function onEditVariables(newVariables) {\n        parameters.variables = newVariables;\n        updateURL();\n      }\n      function onEditOperationName(newOperationName) {\n        parameters.operationName = newOperationName;\n        updateURL();\n      }\n      function updateURL() {\n        var newSearch = '?' + Object.keys(parameters).filter(function (key) {\n          return Boolean(parameters[key]);\n        }).map(function (key) {\n          return encodeURIComponent(key) + '=' +\n            encodeURIComponent(parameters[key]);\n        }).join('&');\n        history.replaceState(null, null, newSearch);\n      }\n      // Defines a GraphQL fetcher using the fetch API. You're not required to\n      // use fetch, and could instead implement graphQLFetcher however you like,\n      // as long as it returns a Promise or Observable.\n      function graphQLFetcher(graphQLParams) {\n        // This example expects a GraphQL server at the path /graphql.\n        // Change this to point wherever you host your GraphQL server.\n        return fetch({{REQUEST_PATH}}, {\n          method: 'post',\n          headers: {\n            'Accept': 'application/json',\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify(graphQLParams),\n          credentials: 'include',\n        }).then(function (response) {\n          return response.text();\n        }).then(function (responseBody) {\n          try {\n            return JSON.parse(responseBody);\n          } catch (error) {\n            return responseBody;\n          }\n        });\n      }\n      // Render <GraphiQL /> into the body.\n      // See the README in the top level of this module to learn more about\n      // how you can customize GraphiQL by providing different values or\n      // additional child elements.\n      ReactDOM.render(\n        React.createElement(GraphiQL, {\n          fetcher: graphQLFetcher,\n          query: parameters.query,\n          variables: parameters.variables,\n          operationName: parameters.operationName,\n          onEditQuery: onEditQuery,\n          onEditVariables: onEditVariables,\n          onEditOperationName: onEditOperationName\n        }),\n        document.getElementById('graphiql')\n      );\n    </script>\n  </body>\n</html>\n\"\"\"\n", "path": "starlette/graphql.py"}], "after_files": [{"content": "import asyncio\nimport typing\n\nfrom starlette.concurrency import run_in_threadpool\n\n\nclass BackgroundTask:\n    def __init__(\n        self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any\n    ) -> None:\n        self.func = func\n        self.args = args\n        self.kwargs = kwargs\n        self.is_async = asyncio.iscoroutinefunction(func)\n\n    async def __call__(self) -> None:\n        if self.is_async:\n            await self.func(*self.args, **self.kwargs)\n        else:\n            await run_in_threadpool(self.func, *self.args, **self.kwargs)\n\n\nclass BackgroundTasks(BackgroundTask):\n    def __init__(self, tasks: typing.Sequence[BackgroundTask] = []):\n        self.tasks = list(tasks)\n\n    def add_task(\n        self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any\n    ) -> None:\n        task = BackgroundTask(func, *args, **kwargs)\n        self.tasks.append(task)\n\n    async def __call__(self) -> None:\n        for task in self.tasks:\n            await task()\n", "path": "starlette/background.py"}, {"content": "import functools\nimport json\nimport typing\n\nfrom starlette import status\nfrom starlette.background import BackgroundTasks\nfrom starlette.concurrency import run_in_threadpool\nfrom starlette.requests import Request\nfrom starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response\nfrom starlette.types import ASGIInstance, Receive, Scope, Send\n\ntry:\n    import graphene\n    from graphql.execution.executors.asyncio import AsyncioExecutor\n    from graphql.error import format_error as format_graphql_error\n    from graphql.error import GraphQLError\nexcept ImportError:  # pragma: nocover\n    graphene = None  # type: ignore\n    AsyncioExecutor = None  # type: ignore\n    format_graphql_error = None  # type: ignore\n    GraphQLError = None  # type: ignore\n\n\nclass GraphQLApp:\n    def __init__(self, schema: \"graphene.Schema\", executor: typing.Any = None) -> None:\n        self.schema = schema\n        self.executor = executor\n        self.is_async = isinstance(executor, AsyncioExecutor)\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return functools.partial(self.asgi, scope=scope)\n\n    async def asgi(self, receive: Receive, send: Send, scope: Scope) -> None:\n        request = Request(scope, receive=receive)\n        response = await self.handle_graphql(request)\n        await response(receive, send)\n\n    async def handle_graphql(self, request: Request) -> Response:\n        if request.method == \"GET\":\n            if \"text/html\" in request.headers.get(\"Accept\", \"\"):\n                return await self.handle_graphiql(request)\n\n            data = request.query_params  # type: typing.Mapping[str, typing.Any]\n\n        elif request.method == \"POST\":\n            content_type = request.headers.get(\"Content-Type\", \"\")\n\n            if \"application/json\" in content_type:\n                data = await request.json()\n            elif \"application/graphql\" in content_type:\n                body = await request.body()\n                text = body.decode()\n                data = {\"query\": text}\n            elif \"query\" in request.query_params:\n                data = request.query_params\n            else:\n                return PlainTextResponse(\n                    \"Unsupported Media Type\",\n                    status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,\n                )\n\n        else:\n            return PlainTextResponse(\n                \"Method Not Allowed\", status_code=status.HTTP_405_METHOD_NOT_ALLOWED\n            )\n\n        try:\n            query = data[\"query\"]\n            variables = data.get(\"variables\")\n            operation_name = data.get(\"operationName\")\n        except KeyError:\n            return PlainTextResponse(\n                \"No GraphQL query found in the request\",\n                status_code=status.HTTP_400_BAD_REQUEST,\n            )\n\n        background = BackgroundTasks()\n        context = {\"request\": request, \"background\": background}\n\n        result = await self.execute(query, variables=variables, context=context)\n        error_data = (\n            [format_graphql_error(err) for err in result.errors]\n            if result.errors\n            else None\n        )\n        response_data = {\"data\": result.data, \"errors\": error_data}\n        status_code = (\n            status.HTTP_400_BAD_REQUEST if result.errors else status.HTTP_200_OK\n        )\n\n        return JSONResponse(\n            response_data, status_code=status_code, background=background\n        )\n\n    async def execute(  # type: ignore\n        self, query, variables=None, context=None, operation_name=None\n    ):\n        if self.is_async:\n            return await self.schema.execute(\n                query,\n                variables=variables,\n                operation_name=operation_name,\n                executor=self.executor,\n                return_promise=True,\n                context=context,\n            )\n        else:\n            return await run_in_threadpool(\n                self.schema.execute,\n                query,\n                variables=variables,\n                operation_name=operation_name,\n                context=context,\n            )\n\n    async def handle_graphiql(self, request: Request) -> Response:\n        text = GRAPHIQL.replace(\"{{REQUEST_PATH}}\", json.dumps(request.url.path))\n        return HTMLResponse(text)\n\n\nGRAPHIQL = \"\"\"\n<!--\n *  Copyright (c) Facebook, Inc.\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n      #graphiql {\n        height: 100vh;\n      }\n    </style>\n    <!--\n      This GraphiQL example depends on Promise and fetch, which are available in\n      modern browsers, but can be \"polyfilled\" for older browsers.\n      GraphiQL itself depends on React DOM.\n      If you do not want to rely on a CDN, you can host these files locally or\n      include them directly in your favored resource bunder.\n    -->\n    <link href=\"//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.css\" rel=\"stylesheet\"/>\n    <script src=\"//cdn.jsdelivr.net/npm/whatwg-fetch@2.0.3/fetch.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/react@16.2.0/umd/react.production.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/react-dom@16.2.0/umd/react-dom.production.min.js\"></script>\n    <script src=\"//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"graphiql\">Loading...</div>\n    <script>\n      /**\n       * This GraphiQL example illustrates how to use some of GraphiQL's props\n       * in order to enable reading and updating the URL parameters, making\n       * link sharing of queries a little bit easier.\n       *\n       * This is only one example of this kind of feature, GraphiQL exposes\n       * various React params to enable interesting integrations.\n       */\n      // Parse the search string to get url parameters.\n      var search = window.location.search;\n      var parameters = {};\n      search.substr(1).split('&').forEach(function (entry) {\n        var eq = entry.indexOf('=');\n        if (eq >= 0) {\n          parameters[decodeURIComponent(entry.slice(0, eq))] =\n            decodeURIComponent(entry.slice(eq + 1));\n        }\n      });\n      // if variables was provided, try to format it.\n      if (parameters.variables) {\n        try {\n          parameters.variables =\n            JSON.stringify(JSON.parse(parameters.variables), null, 2);\n        } catch (e) {\n          // Do nothing, we want to display the invalid JSON as a string, rather\n          // than present an error.\n        }\n      }\n      // When the query and variables string is edited, update the URL bar so\n      // that it can be easily shared\n      function onEditQuery(newQuery) {\n        parameters.query = newQuery;\n        updateURL();\n      }\n      function onEditVariables(newVariables) {\n        parameters.variables = newVariables;\n        updateURL();\n      }\n      function onEditOperationName(newOperationName) {\n        parameters.operationName = newOperationName;\n        updateURL();\n      }\n      function updateURL() {\n        var newSearch = '?' + Object.keys(parameters).filter(function (key) {\n          return Boolean(parameters[key]);\n        }).map(function (key) {\n          return encodeURIComponent(key) + '=' +\n            encodeURIComponent(parameters[key]);\n        }).join('&');\n        history.replaceState(null, null, newSearch);\n      }\n      // Defines a GraphQL fetcher using the fetch API. You're not required to\n      // use fetch, and could instead implement graphQLFetcher however you like,\n      // as long as it returns a Promise or Observable.\n      function graphQLFetcher(graphQLParams) {\n        // This example expects a GraphQL server at the path /graphql.\n        // Change this to point wherever you host your GraphQL server.\n        return fetch({{REQUEST_PATH}}, {\n          method: 'post',\n          headers: {\n            'Accept': 'application/json',\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify(graphQLParams),\n          credentials: 'include',\n        }).then(function (response) {\n          return response.text();\n        }).then(function (responseBody) {\n          try {\n            return JSON.parse(responseBody);\n          } catch (error) {\n            return responseBody;\n          }\n        });\n      }\n      // Render <GraphiQL /> into the body.\n      // See the README in the top level of this module to learn more about\n      // how you can customize GraphiQL by providing different values or\n      // additional child elements.\n      ReactDOM.render(\n        React.createElement(GraphiQL, {\n          fetcher: graphQLFetcher,\n          query: parameters.query,\n          variables: parameters.variables,\n          operationName: parameters.operationName,\n          onEditQuery: onEditQuery,\n          onEditVariables: onEditVariables,\n          onEditOperationName: onEditOperationName\n        }),\n        document.getElementById('graphiql')\n      );\n    </script>\n  </body>\n</html>\n\"\"\"\n", "path": "starlette/graphql.py"}]}