We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
OSError: Failed to load return from the HEKClient.
When trying to search for the flares on 2014/10/24 to /25, I get a "Failed to Load Return" error. 
Sunpy Version: 1.1.3

Here's a minimal reproducible example:

```
from sunpy.net import hek
client = hek.HEKClient()
tstart = '2014/10/24 20:50'
tend   = '2014/10/25 00:14'
event_type = 'FL'
client.search(hek.attrs.Time(tstart,tend),hek.attrs.EventType(event_type))
```



```python
Traceback (most recent call last):
  File "/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py", line 69, in _download
    result = json.load(fd)
  File "/home/user/anaconda3/envs/pytorch/lib/python3.8/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/home/user/anaconda3/envs/pytorch/lib/python3.8/json/__init__.py", line 343, in loads
    s = s.decode(detect_encoding(s), 'surrogatepass')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc5 in position 33279: invalid continuation byte

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py", line 99, in search
    return self._download(ndata[0])
  File "/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py", line 71, in _download
    raise IOError("Failed to load return from the HEKClient.") from e
OSError: Failed to load return from the HEKClient.
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sunpy/net/hek/hek.py`
Content:
```
1 """
2 Facilities to interface with the Heliophysics Events Knowledgebase.
3 """
4 
5 import json
6 
7 import urllib
8 from itertools import chain
9 
10 from astropy.table import Table, Row, Column
11 from astropy.time import Time
12 
13 from sunpy.net import attr
14 from sunpy.util import dict_keys_same, unique
15 from sunpy.net.hek import attrs
16 import sunpy.net._attrs as core_attrs
17 from sunpy.util.xml import xml_to_dict
18 
19 
20 __all__ = ['HEKClient']
21 
22 DEFAULT_URL = 'https://www.lmsal.com/hek/her?'
23 
24 
25 def _freeze(obj):
26     """ Create hashable representation of result dict. """
27     if isinstance(obj, dict):
28         return tuple((k, _freeze(v)) for k, v in obj.items())
29     if isinstance(obj, list):
30         return tuple(_freeze(elem) for elem in obj)
31     return obj
32 
33 
34 class HEKClient:
35     """ Client to interact with the Heliophysics Event Knowledgebase (HEK).
36     The HEK stores solar feature and event data generated by algorithms and
37     human observers."""
38     # FIXME: Expose fields in .attrs with the right types
39     # that is, not all StringParamWrapper!
40 
41     default = {
42         'cosec': '2',
43         'cmd': 'search',
44         'type': 'column',
45         'event_type': '**',
46     }
47     # Default to full disk.
48     attrs.walker.apply(attrs.SpatialRegion(), {}, default)
49 
50     def __init__(self, url=DEFAULT_URL):
51         self.url = url
52 
53     def _download(self, data):
54         """ Download all data, even if paginated. """
55         page = 1
56         results = []
57 
58         while True:
59             data['page'] = page
60             fd = urllib.request.urlopen(self.url+urllib.parse.urlencode(data))
61             try:
62                 result = json.load(fd)
63             except Exception as e:
64                 raise IOError("Failed to load return from the HEKClient.") from e
65             finally:
66                 fd.close()
67             results.extend(result['result'])
68 
69             if not result['overmax']:
70                 if len(results) > 0:
71                     return HEKTable(dict_keys_same(results))
72                 else:
73                     return HEKTable()
74 
75             page += 1
76 
77     def search(self, *query):
78         """ Retrieves information about HEK records matching the criteria
79         given in the query expression. If multiple arguments are passed,
80         they are connected with AND. The result of a query is a list of
81         unique HEK Response objects that fulfill the criteria."""
82         query = attr.and_(*query)
83 
84         data = attrs.walker.create(query, {})
85         ndata = []
86         for elem in data:
87             new = self.default.copy()
88             new.update(elem)
89             ndata.append(new)
90 
91         if len(ndata) == 1:
92             return self._download(ndata[0])
93         else:
94             return self._merge(self._download(data) for data in ndata)
95 
96     def _merge(self, responses):
97         """ Merge responses, removing duplicates. """
98         return list(unique(chain.from_iterable(responses), _freeze))
99 
100 
101 class HEKTable(Table):
102     def __getitem__(self, item):
103         table_item = super().__getitem__(item)
104 
105         if table_item.__class__ == Column:
106             table_item.__class__ = HEKColumn
107         elif table_item.__class__ == Row:
108             table_item.__class__ = HEKRow
109 
110         return table_item
111 
112 
113 class HEKColumn(Column):
114     pass
115 
116 
117 class HEKRow(Row):
118     """
119     Handles the response from the HEK.  Each HEKRow object is a subclass
120     of `astropy.Table.row`.  The column-row key-value pairs correspond to the
121     HEK feature/event properties and their values, for that record from the
122     HEK.  Each HEKRow object also has extra properties that relate HEK
123     concepts to VSO concepts.
124     """
125     @property
126     def vso_time(self):
127         return core_attrs.Time(
128             Time.strptime(self['event_starttime'], "%Y-%m-%dT%H:%M:%S"),
129             Time.strptime(self['event_endtime'], "%Y-%m-%dT%H:%M:%S")
130         )
131 
132     @property
133     def vso_instrument(self):
134         if self['obs_instrument'] == 'HEK':
135             raise ValueError("No instrument contained.")
136         return core_attrs.Instrument(self['obs_instrument'])
137 
138     @property
139     def vso_all(self):
140         return attr.and_(self.vso_time, self.vso_instrument)
141 
142     def get_voevent(self, as_dict=True,
143                     base_url="http://www.lmsal.com/hek/her?"):
144         """Retrieves the VOEvent object associated with a given event and
145         returns it as either a Python dictionary or an XML string."""
146 
147         # Build URL
148         params = {
149             "cmd": "export-voevent",
150             "cosec": 1,
151             "ivorn": self['kb_archivid']
152         }
153         url = base_url + urllib.parse.urlencode(params)
154 
155         # Query and read response
156         response = urllib.request.urlopen(url).read()
157 
158         # Return a string or dict
159         if as_dict:
160             return xml_to_dict(response)
161         else:
162             return response
163 
164     def get(self, key, default=None):
165         try:
166             return self[key]
167         except KeyError:
168             return default
169
```
--- 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/sunpy/net/hek/hek.py b/sunpy/net/hek/hek.py
--- a/sunpy/net/hek/hek.py
+++ b/sunpy/net/hek/hek.py
@@ -1,8 +1,8 @@
 """
 Facilities to interface with the Heliophysics Events Knowledgebase.
 """
-
 import json
+import codecs
 
 import urllib
 from itertools import chain
@@ -59,7 +59,8 @@
             data['page'] = page
             fd = urllib.request.urlopen(self.url+urllib.parse.urlencode(data))
             try:
-                result = json.load(fd)
+                result = codecs.decode(fd.read(), encoding='utf-8', errors='replace')
+                result = json.loads(result)
             except Exception as e:
                 raise IOError("Failed to load return from the HEKClient.") from e
             finally:

{"golden_diff": "diff --git a/sunpy/net/hek/hek.py b/sunpy/net/hek/hek.py\n--- a/sunpy/net/hek/hek.py\n+++ b/sunpy/net/hek/hek.py\n@@ -1,8 +1,8 @@\n \"\"\"\n Facilities to interface with the Heliophysics Events Knowledgebase.\n \"\"\"\n-\n import json\n+import codecs\n \n import urllib\n from itertools import chain\n@@ -59,7 +59,8 @@\n             data['page'] = page\n             fd = urllib.request.urlopen(self.url+urllib.parse.urlencode(data))\n             try:\n-                result = json.load(fd)\n+                result = codecs.decode(fd.read(), encoding='utf-8', errors='replace')\n+                result = json.loads(result)\n             except Exception as e:\n                 raise IOError(\"Failed to load return from the HEKClient.\") from e\n             finally:\n", "issue": "OSError: Failed to load return from the HEKClient.\nWhen trying to search for the flares on 2014/10/24 to /25, I get a \"Failed to Load Return\" error. \r\nSunpy Version: 1.1.3\r\n\r\nHere's a minimal reproducible example:\r\n\r\n```\r\nfrom sunpy.net import hek\r\nclient = hek.HEKClient()\r\ntstart = '2014/10/24 20:50'\r\ntend   = '2014/10/25 00:14'\r\nevent_type = 'FL'\r\nclient.search(hek.attrs.Time(tstart,tend),hek.attrs.EventType(event_type))\r\n```\r\n\r\n\r\n\r\n```python\r\nTraceback (most recent call last):\r\n  File \"/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py\", line 69, in _download\r\n    result = json.load(fd)\r\n  File \"/home/user/anaconda3/envs/pytorch/lib/python3.8/json/__init__.py\", line 293, in load\r\n    return loads(fp.read(),\r\n  File \"/home/user/anaconda3/envs/pytorch/lib/python3.8/json/__init__.py\", line 343, in loads\r\n    s = s.decode(detect_encoding(s), 'surrogatepass')\r\nUnicodeDecodeError: 'utf-8' codec can't decode byte 0xc5 in position 33279: invalid continuation byte\r\n\r\nThe above exception was the direct cause of the following exception:\r\n\r\nTraceback (most recent call last):\r\n  File \"<input>\", line 1, in <module>\r\n  File \"/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py\", line 99, in search\r\n    return self._download(ndata[0])\r\n  File \"/home/user/anaconda3/envs/pytorch/lib/python3.8/site-packages/sunpy/net/hek/hek.py\", line 71, in _download\r\n    raise IOError(\"Failed to load return from the HEKClient.\") from e\r\nOSError: Failed to load return from the HEKClient.\r\n```\n", "before_files": [{"content": "\"\"\"\nFacilities to interface with the Heliophysics Events Knowledgebase.\n\"\"\"\n\nimport json\n\nimport urllib\nfrom itertools import chain\n\nfrom astropy.table import Table, Row, Column\nfrom astropy.time import Time\n\nfrom sunpy.net import attr\nfrom sunpy.util import dict_keys_same, unique\nfrom sunpy.net.hek import attrs\nimport sunpy.net._attrs as core_attrs\nfrom sunpy.util.xml import xml_to_dict\n\n\n__all__ = ['HEKClient']\n\nDEFAULT_URL = 'https://www.lmsal.com/hek/her?'\n\n\ndef _freeze(obj):\n    \"\"\" Create hashable representation of result dict. \"\"\"\n    if isinstance(obj, dict):\n        return tuple((k, _freeze(v)) for k, v in obj.items())\n    if isinstance(obj, list):\n        return tuple(_freeze(elem) for elem in obj)\n    return obj\n\n\nclass HEKClient:\n    \"\"\" Client to interact with the Heliophysics Event Knowledgebase (HEK).\n    The HEK stores solar feature and event data generated by algorithms and\n    human observers.\"\"\"\n    # FIXME: Expose fields in .attrs with the right types\n    # that is, not all StringParamWrapper!\n\n    default = {\n        'cosec': '2',\n        'cmd': 'search',\n        'type': 'column',\n        'event_type': '**',\n    }\n    # Default to full disk.\n    attrs.walker.apply(attrs.SpatialRegion(), {}, default)\n\n    def __init__(self, url=DEFAULT_URL):\n        self.url = url\n\n    def _download(self, data):\n        \"\"\" Download all data, even if paginated. \"\"\"\n        page = 1\n        results = []\n\n        while True:\n            data['page'] = page\n            fd = urllib.request.urlopen(self.url+urllib.parse.urlencode(data))\n            try:\n                result = json.load(fd)\n            except Exception as e:\n                raise IOError(\"Failed to load return from the HEKClient.\") from e\n            finally:\n                fd.close()\n            results.extend(result['result'])\n\n            if not result['overmax']:\n                if len(results) > 0:\n                    return HEKTable(dict_keys_same(results))\n                else:\n                    return HEKTable()\n\n            page += 1\n\n    def search(self, *query):\n        \"\"\" Retrieves information about HEK records matching the criteria\n        given in the query expression. If multiple arguments are passed,\n        they are connected with AND. The result of a query is a list of\n        unique HEK Response objects that fulfill the criteria.\"\"\"\n        query = attr.and_(*query)\n\n        data = attrs.walker.create(query, {})\n        ndata = []\n        for elem in data:\n            new = self.default.copy()\n            new.update(elem)\n            ndata.append(new)\n\n        if len(ndata) == 1:\n            return self._download(ndata[0])\n        else:\n            return self._merge(self._download(data) for data in ndata)\n\n    def _merge(self, responses):\n        \"\"\" Merge responses, removing duplicates. \"\"\"\n        return list(unique(chain.from_iterable(responses), _freeze))\n\n\nclass HEKTable(Table):\n    def __getitem__(self, item):\n        table_item = super().__getitem__(item)\n\n        if table_item.__class__ == Column:\n            table_item.__class__ = HEKColumn\n        elif table_item.__class__ == Row:\n            table_item.__class__ = HEKRow\n\n        return table_item\n\n\nclass HEKColumn(Column):\n    pass\n\n\nclass HEKRow(Row):\n    \"\"\"\n    Handles the response from the HEK.  Each HEKRow object is a subclass\n    of `astropy.Table.row`.  The column-row key-value pairs correspond to the\n    HEK feature/event properties and their values, for that record from the\n    HEK.  Each HEKRow object also has extra properties that relate HEK\n    concepts to VSO concepts.\n    \"\"\"\n    @property\n    def vso_time(self):\n        return core_attrs.Time(\n            Time.strptime(self['event_starttime'], \"%Y-%m-%dT%H:%M:%S\"),\n            Time.strptime(self['event_endtime'], \"%Y-%m-%dT%H:%M:%S\")\n        )\n\n    @property\n    def vso_instrument(self):\n        if self['obs_instrument'] == 'HEK':\n            raise ValueError(\"No instrument contained.\")\n        return core_attrs.Instrument(self['obs_instrument'])\n\n    @property\n    def vso_all(self):\n        return attr.and_(self.vso_time, self.vso_instrument)\n\n    def get_voevent(self, as_dict=True,\n                    base_url=\"http://www.lmsal.com/hek/her?\"):\n        \"\"\"Retrieves the VOEvent object associated with a given event and\n        returns it as either a Python dictionary or an XML string.\"\"\"\n\n        # Build URL\n        params = {\n            \"cmd\": \"export-voevent\",\n            \"cosec\": 1,\n            \"ivorn\": self['kb_archivid']\n        }\n        url = base_url + urllib.parse.urlencode(params)\n\n        # Query and read response\n        response = urllib.request.urlopen(url).read()\n\n        # Return a string or dict\n        if as_dict:\n            return xml_to_dict(response)\n        else:\n            return response\n\n    def get(self, key, default=None):\n        try:\n            return self[key]\n        except KeyError:\n            return default\n", "path": "sunpy/net/hek/hek.py"}], "after_files": [{"content": "\"\"\"\nFacilities to interface with the Heliophysics Events Knowledgebase.\n\"\"\"\nimport json\nimport codecs\n\nimport urllib\nfrom itertools import chain\n\nfrom astropy.table import Table, Row, Column\nfrom astropy.time import Time\n\nfrom sunpy.net import attr\nfrom sunpy.util import dict_keys_same, unique\nfrom sunpy.net.hek import attrs\nimport sunpy.net._attrs as core_attrs\nfrom sunpy.util.xml import xml_to_dict\n\n\n__all__ = ['HEKClient']\n\nDEFAULT_URL = 'https://www.lmsal.com/hek/her?'\n\n\ndef _freeze(obj):\n    \"\"\" Create hashable representation of result dict. \"\"\"\n    if isinstance(obj, dict):\n        return tuple((k, _freeze(v)) for k, v in obj.items())\n    if isinstance(obj, list):\n        return tuple(_freeze(elem) for elem in obj)\n    return obj\n\n\nclass HEKClient:\n    \"\"\" Client to interact with the Heliophysics Event Knowledgebase (HEK).\n    The HEK stores solar feature and event data generated by algorithms and\n    human observers.\"\"\"\n    # FIXME: Expose fields in .attrs with the right types\n    # that is, not all StringParamWrapper!\n\n    default = {\n        'cosec': '2',\n        'cmd': 'search',\n        'type': 'column',\n        'event_type': '**',\n    }\n    # Default to full disk.\n    attrs.walker.apply(attrs.SpatialRegion(), {}, default)\n\n    def __init__(self, url=DEFAULT_URL):\n        self.url = url\n\n    def _download(self, data):\n        \"\"\" Download all data, even if paginated. \"\"\"\n        page = 1\n        results = []\n\n        while True:\n            data['page'] = page\n            fd = urllib.request.urlopen(self.url+urllib.parse.urlencode(data))\n            try:\n                result = codecs.decode(fd.read(), encoding='utf-8', errors='replace')\n                result = json.loads(result)\n            except Exception as e:\n                raise IOError(\"Failed to load return from the HEKClient.\") from e\n            finally:\n                fd.close()\n            results.extend(result['result'])\n\n            if not result['overmax']:\n                if len(results) > 0:\n                    return HEKTable(dict_keys_same(results))\n                else:\n                    return HEKTable()\n\n            page += 1\n\n    def search(self, *query):\n        \"\"\" Retrieves information about HEK records matching the criteria\n        given in the query expression. If multiple arguments are passed,\n        they are connected with AND. The result of a query is a list of\n        unique HEK Response objects that fulfill the criteria.\"\"\"\n        query = attr.and_(*query)\n\n        data = attrs.walker.create(query, {})\n        ndata = []\n        for elem in data:\n            new = self.default.copy()\n            new.update(elem)\n            ndata.append(new)\n\n        if len(ndata) == 1:\n            return self._download(ndata[0])\n        else:\n            return self._merge(self._download(data) for data in ndata)\n\n    def _merge(self, responses):\n        \"\"\" Merge responses, removing duplicates. \"\"\"\n        return list(unique(chain.from_iterable(responses), _freeze))\n\n\nclass HEKTable(Table):\n    def __getitem__(self, item):\n        table_item = super().__getitem__(item)\n\n        if table_item.__class__ == Column:\n            table_item.__class__ = HEKColumn\n        elif table_item.__class__ == Row:\n            table_item.__class__ = HEKRow\n\n        return table_item\n\n\nclass HEKColumn(Column):\n    pass\n\n\nclass HEKRow(Row):\n    \"\"\"\n    Handles the response from the HEK.  Each HEKRow object is a subclass\n    of `astropy.Table.row`.  The column-row key-value pairs correspond to the\n    HEK feature/event properties and their values, for that record from the\n    HEK.  Each HEKRow object also has extra properties that relate HEK\n    concepts to VSO concepts.\n    \"\"\"\n    @property\n    def vso_time(self):\n        return core_attrs.Time(\n            Time.strptime(self['event_starttime'], \"%Y-%m-%dT%H:%M:%S\"),\n            Time.strptime(self['event_endtime'], \"%Y-%m-%dT%H:%M:%S\")\n        )\n\n    @property\n    def vso_instrument(self):\n        if self['obs_instrument'] == 'HEK':\n            raise ValueError(\"No instrument contained.\")\n        return core_attrs.Instrument(self['obs_instrument'])\n\n    @property\n    def vso_all(self):\n        return attr.and_(self.vso_time, self.vso_instrument)\n\n    def get_voevent(self, as_dict=True,\n                    base_url=\"http://www.lmsal.com/hek/her?\"):\n        \"\"\"Retrieves the VOEvent object associated with a given event and\n        returns it as either a Python dictionary or an XML string.\"\"\"\n\n        # Build URL\n        params = {\n            \"cmd\": \"export-voevent\",\n            \"cosec\": 1,\n            \"ivorn\": self['kb_archivid']\n        }\n        url = base_url + urllib.parse.urlencode(params)\n\n        # Query and read response\n        response = urllib.request.urlopen(url).read()\n\n        # Return a string or dict\n        if as_dict:\n            return xml_to_dict(response)\n        else:\n            return response\n\n    def get(self, key, default=None):\n        try:\n            return self[key]\n        except KeyError:\n            return default\n", "path": "sunpy/net/hek/hek.py"}]}