We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Specify a User Agent for HTTP requests
Right now it's python-urllib/someversion, and Cloudflare sites (tested on medium protection site) blocks it and returns 403 status code.
Testing the same url with curl works without it blocking, so I'm guessing Cloudflare checks the request UA.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lutris/util/http.py`
Content:
```
1 import json
2 import socket
3 import urllib.request
4 import urllib.error
5 import urllib.parse
6 from ssl import CertificateError
7 
8 from lutris.settings import SITE_URL
9 from lutris.util.log import logger
10 
11 
12 class Request(object):
13     def __init__(self, url, timeout=5, stop_request=None,
14                  thread_queue=None, headers={}):
15 
16         if not url:
17             raise ValueError('An URL is required!')
18 
19         if url.startswith('//'):
20             url = 'https:' + url
21 
22         if url.startswith('/'):
23             url = SITE_URL + url
24 
25         self.url = url
26         self.content = ''
27         self.timeout = timeout
28         self.stop_request = stop_request
29         self.thread_queue = thread_queue
30         self.buffer_size = 32 * 1024  # Bytes
31         self.downloaded_size = 0
32         self.headers = headers
33 
34     def get(self, data=None):
35         req = urllib.request.Request(url=self.url, data=data, headers=self.headers)
36         try:
37             request = urllib.request.urlopen(req, timeout=self.timeout)
38         except (urllib.error.HTTPError, CertificateError) as e:
39             logger.error("Unavailable url (%s): %s", self.url, e)
40         except (socket.timeout, urllib.error.URLError) as e:
41             logger.error("Unable to connect to server (%s): %s", self.url, e)
42         else:
43             try:
44                 total_size = request.info().get('Content-Length').strip()
45                 total_size = int(total_size)
46             except AttributeError:
47                 total_size = 0
48 
49             chunks = []
50             while 1:
51                 if self.stop_request and self.stop_request.is_set():
52                     self.content = ''
53                     return self
54                 try:
55                     chunk = request.read(self.buffer_size)
56                 except socket.timeout as e:
57                     logger.error("Request timed out")
58                     self.content = ''
59                     return self
60                 self.downloaded_size += len(chunk)
61                 if self.thread_queue:
62                     self.thread_queue.put(
63                         (chunk, self.downloaded_size, total_size)
64                     )
65                 else:
66                     chunks.append(chunk)
67                 if not chunk:
68                     break
69             request.close()
70             self.content = b''.join(chunks)
71         return self
72 
73     def post(self, data):
74         raise NotImplementedError
75 
76     def write_to_file(self, path):
77         content = self.content
78         if content:
79             with open(path, 'wb') as dest_file:
80                 dest_file.write(content)
81 
82     @property
83     def json(self):
84         if self.content:
85             return json.loads(self.text)
86 
87     @property
88     def text(self):
89         if self.content:
90             return self.content.decode()
91
```
--- 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/lutris/util/http.py b/lutris/util/http.py
--- a/lutris/util/http.py
+++ b/lutris/util/http.py
@@ -5,6 +5,8 @@
 import urllib.parse
 from ssl import CertificateError
 
+from lutris.settings import PROJECT
+from lutris.settings import VERSION
 from lutris.settings import SITE_URL
 from lutris.util.log import logger
 
@@ -29,6 +31,8 @@
         self.thread_queue = thread_queue
         self.buffer_size = 32 * 1024  # Bytes
         self.downloaded_size = 0
+        if not headers.get('User-Agent'):
+            headers['User-Agent'] = PROJECT + '/' + VERSION
         self.headers = headers
 
     def get(self, data=None):

{"golden_diff": "diff --git a/lutris/util/http.py b/lutris/util/http.py\n--- a/lutris/util/http.py\n+++ b/lutris/util/http.py\n@@ -5,6 +5,8 @@\n import urllib.parse\n from ssl import CertificateError\n \n+from lutris.settings import PROJECT\n+from lutris.settings import VERSION\n from lutris.settings import SITE_URL\n from lutris.util.log import logger\n \n@@ -29,6 +31,8 @@\n         self.thread_queue = thread_queue\n         self.buffer_size = 32 * 1024  # Bytes\n         self.downloaded_size = 0\n+        if not headers.get('User-Agent'):\n+            headers['User-Agent'] = PROJECT + '/' + VERSION\n         self.headers = headers\n \n     def get(self, data=None):\n", "issue": "Specify a User Agent for HTTP requests\nRight now it's python-urllib/someversion, and Cloudflare sites (tested on medium protection site) blocks it and returns 403 status code.\r\nTesting the same url with curl works without it blocking, so I'm guessing Cloudflare checks the request UA.\n", "before_files": [{"content": "import json\nimport socket\nimport urllib.request\nimport urllib.error\nimport urllib.parse\nfrom ssl import CertificateError\n\nfrom lutris.settings import SITE_URL\nfrom lutris.util.log import logger\n\n\nclass Request(object):\n    def __init__(self, url, timeout=5, stop_request=None,\n                 thread_queue=None, headers={}):\n\n        if not url:\n            raise ValueError('An URL is required!')\n\n        if url.startswith('//'):\n            url = 'https:' + url\n\n        if url.startswith('/'):\n            url = SITE_URL + url\n\n        self.url = url\n        self.content = ''\n        self.timeout = timeout\n        self.stop_request = stop_request\n        self.thread_queue = thread_queue\n        self.buffer_size = 32 * 1024  # Bytes\n        self.downloaded_size = 0\n        self.headers = headers\n\n    def get(self, data=None):\n        req = urllib.request.Request(url=self.url, data=data, headers=self.headers)\n        try:\n            request = urllib.request.urlopen(req, timeout=self.timeout)\n        except (urllib.error.HTTPError, CertificateError) as e:\n            logger.error(\"Unavailable url (%s): %s\", self.url, e)\n        except (socket.timeout, urllib.error.URLError) as e:\n            logger.error(\"Unable to connect to server (%s): %s\", self.url, e)\n        else:\n            try:\n                total_size = request.info().get('Content-Length').strip()\n                total_size = int(total_size)\n            except AttributeError:\n                total_size = 0\n\n            chunks = []\n            while 1:\n                if self.stop_request and self.stop_request.is_set():\n                    self.content = ''\n                    return self\n                try:\n                    chunk = request.read(self.buffer_size)\n                except socket.timeout as e:\n                    logger.error(\"Request timed out\")\n                    self.content = ''\n                    return self\n                self.downloaded_size += len(chunk)\n                if self.thread_queue:\n                    self.thread_queue.put(\n                        (chunk, self.downloaded_size, total_size)\n                    )\n                else:\n                    chunks.append(chunk)\n                if not chunk:\n                    break\n            request.close()\n            self.content = b''.join(chunks)\n        return self\n\n    def post(self, data):\n        raise NotImplementedError\n\n    def write_to_file(self, path):\n        content = self.content\n        if content:\n            with open(path, 'wb') as dest_file:\n                dest_file.write(content)\n\n    @property\n    def json(self):\n        if self.content:\n            return json.loads(self.text)\n\n    @property\n    def text(self):\n        if self.content:\n            return self.content.decode()\n", "path": "lutris/util/http.py"}], "after_files": [{"content": "import json\nimport socket\nimport urllib.request\nimport urllib.error\nimport urllib.parse\nfrom ssl import CertificateError\n\nfrom lutris.settings import PROJECT\nfrom lutris.settings import VERSION\nfrom lutris.settings import SITE_URL\nfrom lutris.util.log import logger\n\n\nclass Request(object):\n    def __init__(self, url, timeout=5, stop_request=None,\n                 thread_queue=None, headers={}):\n\n        if not url:\n            raise ValueError('An URL is required!')\n\n        if url.startswith('//'):\n            url = 'https:' + url\n\n        if url.startswith('/'):\n            url = SITE_URL + url\n\n        self.url = url\n        self.content = ''\n        self.timeout = timeout\n        self.stop_request = stop_request\n        self.thread_queue = thread_queue\n        self.buffer_size = 32 * 1024  # Bytes\n        self.downloaded_size = 0\n        if not headers.get('User-Agent'):\n            headers['User-Agent'] = PROJECT + '/' + VERSION\n        self.headers = headers\n\n    def get(self, data=None):\n        req = urllib.request.Request(url=self.url, data=data, headers=self.headers)\n        try:\n            request = urllib.request.urlopen(req, timeout=self.timeout)\n        except (urllib.error.HTTPError, CertificateError) as e:\n            logger.error(\"Unavailable url (%s): %s\", self.url, e)\n        except (socket.timeout, urllib.error.URLError) as e:\n            logger.error(\"Unable to connect to server (%s): %s\", self.url, e)\n        else:\n            try:\n                total_size = request.info().get('Content-Length').strip()\n                total_size = int(total_size)\n            except AttributeError:\n                total_size = 0\n\n            chunks = []\n            while 1:\n                if self.stop_request and self.stop_request.is_set():\n                    self.content = ''\n                    return self\n                try:\n                    chunk = request.read(self.buffer_size)\n                except socket.timeout as e:\n                    logger.error(\"Request timed out\")\n                    self.content = ''\n                    return self\n                self.downloaded_size += len(chunk)\n                if self.thread_queue:\n                    self.thread_queue.put(\n                        (chunk, self.downloaded_size, total_size)\n                    )\n                else:\n                    chunks.append(chunk)\n                if not chunk:\n                    break\n            request.close()\n            self.content = b''.join(chunks)\n        return self\n\n    def post(self, data):\n        raise NotImplementedError\n\n    def write_to_file(self, path):\n        content = self.content\n        if content:\n            with open(path, 'wb') as dest_file:\n                dest_file.write(content)\n\n    @property\n    def json(self):\n        if self.content:\n            return json.loads(self.text)\n\n    @property\n    def text(self):\n        if self.content:\n            return self.content.decode()\n", "path": "lutris/util/http.py"}]}