We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make web server default to all networks
Currently the opsdroid web server is only served on `127.0.0.1` by default. In order to make opsdroid accessible via other networks you much set the `web.host` config option to something else (usually `0.0.0.0`).

This can be misleading for new users and is also causing problems when running on more complex infrastructure like Kubernetes.

I propose that the default is changed to `0.0.0.0` which resolves up front issues but still allows users to lock things down to specific networks if they choose.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `opsdroid/web.py`
Content:
```
1 """Submodule to handle web requests in opsdroid."""
2 
3 import json
4 import logging
5 import ssl
6 
7 from aiohttp import web
8 
9 from opsdroid import __version__
10 
11 
12 _LOGGER = logging.getLogger(__name__)
13 
14 
15 class Web:
16     """Create class for opsdroid Web server."""
17 
18     def __init__(self, opsdroid):
19         """Create web object."""
20         self.opsdroid = opsdroid
21         try:
22             self.config = self.opsdroid.config["web"]
23         except KeyError:
24             self.config = {}
25         self.web_app = web.Application()
26         self.runner = web.AppRunner(self.web_app)
27         self.site = None
28         self.web_app.router.add_get('/', self.web_index_handler)
29         self.web_app.router.add_get('', self.web_index_handler)
30         self.web_app.router.add_get('/stats', self.web_stats_handler)
31         self.web_app.router.add_get('/stats/', self.web_stats_handler)
32 
33     @property
34     def get_port(self):
35         """Return port from config or the default.
36 
37         Args:
38             self: instance method
39 
40         Returns:
41             int: returns value of port being used, config or default
42 
43         """
44         try:
45             port = self.config["port"]
46         except KeyError:
47             if self.get_ssl_context is not None:
48                 port = 8443
49             else:
50                 port = 8080
51         return port
52 
53     @property
54     def get_host(self):
55         """Return host from config or the default.
56 
57         Args:
58             self: instance method
59 
60         Returns:
61             string: returns address of host being used, config or default
62 
63         """
64         try:
65             host = self.config["host"]
66         except KeyError:
67             host = '127.0.0.1'
68         return host
69 
70     @property
71     def get_ssl_context(self):
72         """Return the ssl context or None.
73 
74         Args:
75             self: instance method
76 
77         Returns:
78             string (or NoneType): returns ssl context of None.
79 
80         """
81         try:
82             ssl_config = self.config["ssl"]
83             sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
84             sslcontext.load_cert_chain(ssl_config["cert"], ssl_config["key"])
85             return sslcontext
86         except FileNotFoundError:
87             _LOGGER.error(_("Cannot find ssl cert or key."))
88             return None
89         except KeyError:
90             return None
91 
92     async def start(self):
93         """Start web servers."""
94         _LOGGER.info(_("Started web server on %s://%s%s"),
95                      "http" if self.get_ssl_context is None else "https",
96                      self.get_host,
97                      ":{}".format(self.get_port)
98                      if self.get_port not in (80, 443) else "")
99         await self.runner.setup()
100         self.site = web.TCPSite(self.runner,
101                                 host=self.get_host,
102                                 port=self.get_port,
103                                 ssl_context=self.get_ssl_context)
104         await self.site.start()
105 
106     async def stop(self):
107         """Stop the web server."""
108         await self.runner.cleanup()
109 
110     @staticmethod
111     def build_response(status, result):
112         """Build a json response object to power the bot reponses.
113 
114         Args:
115             result: serialize obj as a JSON formated stream
116 
117         Returns:
118             json: returns json object with list of responses for the bot
119 
120         """
121         return web.Response(text=json.dumps(result), status=status)
122 
123     def register_skill(self, opsdroid, skill, webhook):
124         """Register a new skill in the web app router."""
125         async def wrapper(req, opsdroid=opsdroid, config=skill.config):
126             """Wrap up the aiohttp handler."""
127             _LOGGER.info(_("Running skill %s via webhook"), webhook)
128             opsdroid.stats["webhooks_called"] = \
129                 opsdroid.stats["webhooks_called"] + 1
130             resp = await skill(opsdroid, config, req)
131             if isinstance(resp, web.Response):
132                 return resp
133             return Web.build_response(200, {"called_skill": webhook})
134 
135         self.web_app.router.add_post(
136             "/skill/{}/{}".format(skill.config["name"], webhook), wrapper)
137         self.web_app.router.add_post(
138             "/skill/{}/{}/".format(skill.config["name"], webhook), wrapper)
139 
140     def setup_webhooks(self, skills):
141         """Add the webhooks for the webhook skills to the router."""
142         for skill in skills:
143             for matcher in skill.matchers:
144                 if "webhook" in matcher:
145                     self.register_skill(
146                         self.opsdroid, skill, matcher["webhook"]
147                     )
148 
149     async def web_index_handler(self, request):
150         """Handle root web request to opsdroid API.
151 
152         Args:
153             request: web request to the root (index)
154 
155         Returns:
156             dict: returns successful status code and greeting for the root page
157 
158         """
159         return self.build_response(200, {
160             "message": "Welcome to the opsdroid API"})
161 
162     async def web_stats_handler(self, request):
163         """Handle stats request.
164 
165         Args:
166             request: web request to render opsdroid stats
167 
168         Returns:
169             dict: returns successful status code and dictionary with
170                   stats requested
171 
172         """
173         stats = self.opsdroid.stats
174         try:
175             stats["average_response_time"] = \
176                 stats["total_response_time"] / stats["total_responses"]
177         except ZeroDivisionError:
178             stats["average_response_time"] = 0
179 
180         return self.build_response(200, {
181             "version": __version__,
182             "messages": {
183                 "total_parsed": stats["messages_parsed"],
184                 "webhooks_called": stats["webhooks_called"],
185                 "total_response_time": stats["total_response_time"],
186                 "total_responses": stats["total_responses"],
187                 "average_response_time": stats["average_response_time"]
188             },
189             "modules": {
190                 "skills": len(self.opsdroid.skills),
191                 "connectors": len(self.opsdroid.connectors),
192                 "databases": len(self.opsdroid.memory.databases)
193             }
194         })
195
```
--- 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/opsdroid/web.py b/opsdroid/web.py
--- a/opsdroid/web.py
+++ b/opsdroid/web.py
@@ -64,7 +64,7 @@
         try:
             host = self.config["host"]
         except KeyError:
-            host = '127.0.0.1'
+            host = '0.0.0.0'
         return host
 
     @property

{"golden_diff": "diff --git a/opsdroid/web.py b/opsdroid/web.py\n--- a/opsdroid/web.py\n+++ b/opsdroid/web.py\n@@ -64,7 +64,7 @@\n         try:\n             host = self.config[\"host\"]\n         except KeyError:\n-            host = '127.0.0.1'\n+            host = '0.0.0.0'\n         return host\n \n     @property\n", "issue": "Make web server default to all networks\nCurrently the opsdroid web server is only served on `127.0.0.1` by default. In order to make opsdroid accessible via other networks you much set the `web.host` config option to something else (usually `0.0.0.0`).\r\n\r\nThis can be misleading for new users and is also causing problems when running on more complex infrastructure like Kubernetes.\r\n\r\nI propose that the default is changed to `0.0.0.0` which resolves up front issues but still allows users to lock things down to specific networks if they choose.\n", "before_files": [{"content": "\"\"\"Submodule to handle web requests in opsdroid.\"\"\"\n\nimport json\nimport logging\nimport ssl\n\nfrom aiohttp import web\n\nfrom opsdroid import __version__\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Web:\n    \"\"\"Create class for opsdroid Web server.\"\"\"\n\n    def __init__(self, opsdroid):\n        \"\"\"Create web object.\"\"\"\n        self.opsdroid = opsdroid\n        try:\n            self.config = self.opsdroid.config[\"web\"]\n        except KeyError:\n            self.config = {}\n        self.web_app = web.Application()\n        self.runner = web.AppRunner(self.web_app)\n        self.site = None\n        self.web_app.router.add_get('/', self.web_index_handler)\n        self.web_app.router.add_get('', self.web_index_handler)\n        self.web_app.router.add_get('/stats', self.web_stats_handler)\n        self.web_app.router.add_get('/stats/', self.web_stats_handler)\n\n    @property\n    def get_port(self):\n        \"\"\"Return port from config or the default.\n\n        Args:\n            self: instance method\n\n        Returns:\n            int: returns value of port being used, config or default\n\n        \"\"\"\n        try:\n            port = self.config[\"port\"]\n        except KeyError:\n            if self.get_ssl_context is not None:\n                port = 8443\n            else:\n                port = 8080\n        return port\n\n    @property\n    def get_host(self):\n        \"\"\"Return host from config or the default.\n\n        Args:\n            self: instance method\n\n        Returns:\n            string: returns address of host being used, config or default\n\n        \"\"\"\n        try:\n            host = self.config[\"host\"]\n        except KeyError:\n            host = '127.0.0.1'\n        return host\n\n    @property\n    def get_ssl_context(self):\n        \"\"\"Return the ssl context or None.\n\n        Args:\n            self: instance method\n\n        Returns:\n            string (or NoneType): returns ssl context of None.\n\n        \"\"\"\n        try:\n            ssl_config = self.config[\"ssl\"]\n            sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)\n            sslcontext.load_cert_chain(ssl_config[\"cert\"], ssl_config[\"key\"])\n            return sslcontext\n        except FileNotFoundError:\n            _LOGGER.error(_(\"Cannot find ssl cert or key.\"))\n            return None\n        except KeyError:\n            return None\n\n    async def start(self):\n        \"\"\"Start web servers.\"\"\"\n        _LOGGER.info(_(\"Started web server on %s://%s%s\"),\n                     \"http\" if self.get_ssl_context is None else \"https\",\n                     self.get_host,\n                     \":{}\".format(self.get_port)\n                     if self.get_port not in (80, 443) else \"\")\n        await self.runner.setup()\n        self.site = web.TCPSite(self.runner,\n                                host=self.get_host,\n                                port=self.get_port,\n                                ssl_context=self.get_ssl_context)\n        await self.site.start()\n\n    async def stop(self):\n        \"\"\"Stop the web server.\"\"\"\n        await self.runner.cleanup()\n\n    @staticmethod\n    def build_response(status, result):\n        \"\"\"Build a json response object to power the bot reponses.\n\n        Args:\n            result: serialize obj as a JSON formated stream\n\n        Returns:\n            json: returns json object with list of responses for the bot\n\n        \"\"\"\n        return web.Response(text=json.dumps(result), status=status)\n\n    def register_skill(self, opsdroid, skill, webhook):\n        \"\"\"Register a new skill in the web app router.\"\"\"\n        async def wrapper(req, opsdroid=opsdroid, config=skill.config):\n            \"\"\"Wrap up the aiohttp handler.\"\"\"\n            _LOGGER.info(_(\"Running skill %s via webhook\"), webhook)\n            opsdroid.stats[\"webhooks_called\"] = \\\n                opsdroid.stats[\"webhooks_called\"] + 1\n            resp = await skill(opsdroid, config, req)\n            if isinstance(resp, web.Response):\n                return resp\n            return Web.build_response(200, {\"called_skill\": webhook})\n\n        self.web_app.router.add_post(\n            \"/skill/{}/{}\".format(skill.config[\"name\"], webhook), wrapper)\n        self.web_app.router.add_post(\n            \"/skill/{}/{}/\".format(skill.config[\"name\"], webhook), wrapper)\n\n    def setup_webhooks(self, skills):\n        \"\"\"Add the webhooks for the webhook skills to the router.\"\"\"\n        for skill in skills:\n            for matcher in skill.matchers:\n                if \"webhook\" in matcher:\n                    self.register_skill(\n                        self.opsdroid, skill, matcher[\"webhook\"]\n                    )\n\n    async def web_index_handler(self, request):\n        \"\"\"Handle root web request to opsdroid API.\n\n        Args:\n            request: web request to the root (index)\n\n        Returns:\n            dict: returns successful status code and greeting for the root page\n\n        \"\"\"\n        return self.build_response(200, {\n            \"message\": \"Welcome to the opsdroid API\"})\n\n    async def web_stats_handler(self, request):\n        \"\"\"Handle stats request.\n\n        Args:\n            request: web request to render opsdroid stats\n\n        Returns:\n            dict: returns successful status code and dictionary with\n                  stats requested\n\n        \"\"\"\n        stats = self.opsdroid.stats\n        try:\n            stats[\"average_response_time\"] = \\\n                stats[\"total_response_time\"] / stats[\"total_responses\"]\n        except ZeroDivisionError:\n            stats[\"average_response_time\"] = 0\n\n        return self.build_response(200, {\n            \"version\": __version__,\n            \"messages\": {\n                \"total_parsed\": stats[\"messages_parsed\"],\n                \"webhooks_called\": stats[\"webhooks_called\"],\n                \"total_response_time\": stats[\"total_response_time\"],\n                \"total_responses\": stats[\"total_responses\"],\n                \"average_response_time\": stats[\"average_response_time\"]\n            },\n            \"modules\": {\n                \"skills\": len(self.opsdroid.skills),\n                \"connectors\": len(self.opsdroid.connectors),\n                \"databases\": len(self.opsdroid.memory.databases)\n            }\n        })\n", "path": "opsdroid/web.py"}], "after_files": [{"content": "\"\"\"Submodule to handle web requests in opsdroid.\"\"\"\n\nimport json\nimport logging\nimport ssl\n\nfrom aiohttp import web\n\nfrom opsdroid import __version__\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Web:\n    \"\"\"Create class for opsdroid Web server.\"\"\"\n\n    def __init__(self, opsdroid):\n        \"\"\"Create web object.\"\"\"\n        self.opsdroid = opsdroid\n        try:\n            self.config = self.opsdroid.config[\"web\"]\n        except KeyError:\n            self.config = {}\n        self.web_app = web.Application()\n        self.runner = web.AppRunner(self.web_app)\n        self.site = None\n        self.web_app.router.add_get('/', self.web_index_handler)\n        self.web_app.router.add_get('', self.web_index_handler)\n        self.web_app.router.add_get('/stats', self.web_stats_handler)\n        self.web_app.router.add_get('/stats/', self.web_stats_handler)\n\n    @property\n    def get_port(self):\n        \"\"\"Return port from config or the default.\n\n        Args:\n            self: instance method\n\n        Returns:\n            int: returns value of port being used, config or default\n\n        \"\"\"\n        try:\n            port = self.config[\"port\"]\n        except KeyError:\n            if self.get_ssl_context is not None:\n                port = 8443\n            else:\n                port = 8080\n        return port\n\n    @property\n    def get_host(self):\n        \"\"\"Return host from config or the default.\n\n        Args:\n            self: instance method\n\n        Returns:\n            string: returns address of host being used, config or default\n\n        \"\"\"\n        try:\n            host = self.config[\"host\"]\n        except KeyError:\n            host = '0.0.0.0'\n        return host\n\n    @property\n    def get_ssl_context(self):\n        \"\"\"Return the ssl context or None.\n\n        Args:\n            self: instance method\n\n        Returns:\n            string (or NoneType): returns ssl context of None.\n\n        \"\"\"\n        try:\n            ssl_config = self.config[\"ssl\"]\n            sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)\n            sslcontext.load_cert_chain(ssl_config[\"cert\"], ssl_config[\"key\"])\n            return sslcontext\n        except FileNotFoundError:\n            _LOGGER.error(_(\"Cannot find ssl cert or key.\"))\n            return None\n        except KeyError:\n            return None\n\n    async def start(self):\n        \"\"\"Start web servers.\"\"\"\n        _LOGGER.info(_(\"Started web server on %s://%s%s\"),\n                     \"http\" if self.get_ssl_context is None else \"https\",\n                     self.get_host,\n                     \":{}\".format(self.get_port)\n                     if self.get_port not in (80, 443) else \"\")\n        await self.runner.setup()\n        self.site = web.TCPSite(self.runner,\n                                host=self.get_host,\n                                port=self.get_port,\n                                ssl_context=self.get_ssl_context)\n        await self.site.start()\n\n    async def stop(self):\n        \"\"\"Stop the web server.\"\"\"\n        await self.runner.cleanup()\n\n    @staticmethod\n    def build_response(status, result):\n        \"\"\"Build a json response object to power the bot reponses.\n\n        Args:\n            result: serialize obj as a JSON formated stream\n\n        Returns:\n            json: returns json object with list of responses for the bot\n\n        \"\"\"\n        return web.Response(text=json.dumps(result), status=status)\n\n    def register_skill(self, opsdroid, skill, webhook):\n        \"\"\"Register a new skill in the web app router.\"\"\"\n        async def wrapper(req, opsdroid=opsdroid, config=skill.config):\n            \"\"\"Wrap up the aiohttp handler.\"\"\"\n            _LOGGER.info(_(\"Running skill %s via webhook\"), webhook)\n            opsdroid.stats[\"webhooks_called\"] = \\\n                opsdroid.stats[\"webhooks_called\"] + 1\n            resp = await skill(opsdroid, config, req)\n            if isinstance(resp, web.Response):\n                return resp\n            return Web.build_response(200, {\"called_skill\": webhook})\n\n        self.web_app.router.add_post(\n            \"/skill/{}/{}\".format(skill.config[\"name\"], webhook), wrapper)\n        self.web_app.router.add_post(\n            \"/skill/{}/{}/\".format(skill.config[\"name\"], webhook), wrapper)\n\n    def setup_webhooks(self, skills):\n        \"\"\"Add the webhooks for the webhook skills to the router.\"\"\"\n        for skill in skills:\n            for matcher in skill.matchers:\n                if \"webhook\" in matcher:\n                    self.register_skill(\n                        self.opsdroid, skill, matcher[\"webhook\"]\n                    )\n\n    async def web_index_handler(self, request):\n        \"\"\"Handle root web request to opsdroid API.\n\n        Args:\n            request: web request to the root (index)\n\n        Returns:\n            dict: returns successful status code and greeting for the root page\n\n        \"\"\"\n        return self.build_response(200, {\n            \"message\": \"Welcome to the opsdroid API\"})\n\n    async def web_stats_handler(self, request):\n        \"\"\"Handle stats request.\n\n        Args:\n            request: web request to render opsdroid stats\n\n        Returns:\n            dict: returns successful status code and dictionary with\n                  stats requested\n\n        \"\"\"\n        stats = self.opsdroid.stats\n        try:\n            stats[\"average_response_time\"] = \\\n                stats[\"total_response_time\"] / stats[\"total_responses\"]\n        except ZeroDivisionError:\n            stats[\"average_response_time\"] = 0\n\n        return self.build_response(200, {\n            \"version\": __version__,\n            \"messages\": {\n                \"total_parsed\": stats[\"messages_parsed\"],\n                \"webhooks_called\": stats[\"webhooks_called\"],\n                \"total_response_time\": stats[\"total_response_time\"],\n                \"total_responses\": stats[\"total_responses\"],\n                \"average_response_time\": stats[\"average_response_time\"]\n            },\n            \"modules\": {\n                \"skills\": len(self.opsdroid.skills),\n                \"connectors\": len(self.opsdroid.connectors),\n                \"databases\": len(self.opsdroid.memory.databases)\n            }\n        })\n", "path": "opsdroid/web.py"}]}