prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Add ssl to the web server
  It should be possible to enable ssl on the web server and pass in paths to the ssl keys in the config.
  
  --- 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 
  6 from aiohttp import web
  7 
  8 from opsdroid.const import __version__
  9 
  10 
  11 _LOGGER = logging.getLogger(__name__)
  12 
  13 
  14 class Web:
  15     """Web server for opsdroid."""
  16 
  17     def __init__(self, opsdroid):
  18         """Create web object."""
  19         self.opsdroid = opsdroid
  20         try:
  21             self.config = self.opsdroid.config["web"]
  22         except KeyError:
  23             self.config = {}
  24         self.web_app = web.Application(loop=self.opsdroid.eventloop)
  25         self.web_app.router.add_get('/', self.web_index_handler)
  26         self.web_app.router.add_get('', self.web_index_handler)
  27         self.web_app.router.add_get('/stats', self.web_stats_handler)
  28         self.web_app.router.add_get('/stats/', self.web_stats_handler)
  29 
  30     @property
  31     def get_port(self):
  32         """Return port from config or the default."""
  33         try:
  34             port = self.config["port"]
  35         except KeyError:
  36             port = 8080
  37         return port
  38 
  39     @property
  40     def get_host(self):
  41         """Return host from config or the default."""
  42         try:
  43             host = self.config["host"]
  44         except KeyError:
  45             host = '127.0.0.1'
  46         return host
  47 
  48     def start(self):
  49         """Start web servers."""
  50         _LOGGER.debug(
  51             "Starting web server with host %s and port %s",
  52             self.get_host, self.get_port)
  53         web.run_app(self.web_app, host=self.get_host,
  54                     port=self.get_port, print=_LOGGER.info)
  55 
  56     @staticmethod
  57     def build_response(status, result):
  58         """Build a json response object."""
  59         return web.Response(text=json.dumps(result), status=status)
  60 
  61     def web_index_handler(self, request):
  62         """Handle root web request."""
  63         return self.build_response(200, {
  64             "message": "Welcome to the opsdroid API"})
  65 
  66     def web_stats_handler(self, request):
  67         """Handle stats request."""
  68         stats = self.opsdroid.stats
  69         try:
  70             stats["average_response_time"] = \
  71                 stats["total_response_time"] / stats["total_responses"]
  72         except ZeroDivisionError:
  73             stats["average_response_time"] = 0
  74 
  75         return self.build_response(200, {
  76             "version": __version__,
  77             "messages": {
  78                 "total_parsed": stats["messages_parsed"],
  79                 "webhooks_called": stats["webhooks_called"],
  80                 "total_response_time": stats["total_response_time"],
  81                 "total_responses": stats["total_responses"],
  82                 "average_response_time": stats["average_response_time"]
  83             },
  84             "modules": {
  85                 "skills": len(self.opsdroid.skills),
  86                 "connectors": len(self.opsdroid.connectors),
  87                 "databases": len(self.opsdroid.memory.databases)
  88             }
  89         })
  90
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/opsdroid/web.py b/opsdroid/web.py
  --- a/opsdroid/web.py
  +++ b/opsdroid/web.py
  @@ -2,6 +2,7 @@
   
   import json
   import logging
  +import ssl
   
   from aiohttp import web
   
  @@ -33,7 +34,10 @@
           try:
               port = self.config["port"]
           except KeyError:
  -            port = 8080
  +            if self.get_ssl_context is not None:
  +                port = 8443
  +            else:
  +                port = 8080
           return port
   
       @property
  @@ -45,13 +49,28 @@
               host = '127.0.0.1'
           return host
   
  +    @property
  +    def get_ssl_context(self):
  +        """Return the ssl context or None."""
  +        try:
  +            ssl_config = self.config["ssl"]
  +            sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  +            sslcontext.load_cert_chain(ssl_config["cert"], ssl_config["key"])
  +            return sslcontext
  +        except FileNotFoundError:
  +            _LOGGER.error("Cannot find ssl cert or key.")
  +            return None
  +        except KeyError:
  +            return None
  +
       def start(self):
           """Start web servers."""
           _LOGGER.debug(
               "Starting web server with host %s and port %s",
               self.get_host, self.get_port)
           web.run_app(self.web_app, host=self.get_host,
  -                    port=self.get_port, print=_LOGGER.info)
  +                    port=self.get_port, print=_LOGGER.info,
  +                    ssl_context=self.get_ssl_context)
   
       @staticmethod
       def build_response(status, result):
  
verification_info: {"golden_diff": "diff --git a/opsdroid/web.py b/opsdroid/web.py\n--- a/opsdroid/web.py\n+++ b/opsdroid/web.py\n@@ -2,6 +2,7 @@\n \n import json\n import logging\n+import ssl\n \n from aiohttp import web\n \n@@ -33,7 +34,10 @@\n         try:\n             port = self.config[\"port\"]\n         except KeyError:\n-            port = 8080\n+            if self.get_ssl_context is not None:\n+                port = 8443\n+            else:\n+                port = 8080\n         return port\n \n     @property\n@@ -45,13 +49,28 @@\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+        try:\n+            ssl_config = self.config[\"ssl\"]\n+            sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\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     def start(self):\n         \"\"\"Start web servers.\"\"\"\n         _LOGGER.debug(\n             \"Starting web server with host %s and port %s\",\n             self.get_host, self.get_port)\n         web.run_app(self.web_app, host=self.get_host,\n-                    port=self.get_port, print=_LOGGER.info)\n+                    port=self.get_port, print=_LOGGER.info,\n+                    ssl_context=self.get_ssl_context)\n \n     @staticmethod\n     def build_response(status, result):\n", "issue": "Add ssl to the web server\nIt should be possible to enable ssl on the web server and pass in paths to the ssl keys in the config.\n", "before_files": [{"content": "\"\"\"Submodule to handle web requests in opsdroid.\"\"\"\n\nimport json\nimport logging\n\nfrom aiohttp import web\n\nfrom opsdroid.const import __version__\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Web:\n    \"\"\"Web server for opsdroid.\"\"\"\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(loop=self.opsdroid.eventloop)\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        try:\n            port = self.config[\"port\"]\n        except KeyError:\n            port = 8080\n        return port\n\n    @property\n    def get_host(self):\n        \"\"\"Return host from config or the default.\"\"\"\n        try:\n            host = self.config[\"host\"]\n        except KeyError:\n            host = '127.0.0.1'\n        return host\n\n    def start(self):\n        \"\"\"Start web servers.\"\"\"\n        _LOGGER.debug(\n            \"Starting web server with host %s and port %s\",\n            self.get_host, self.get_port)\n        web.run_app(self.web_app, host=self.get_host,\n                    port=self.get_port, print=_LOGGER.info)\n\n    @staticmethod\n    def build_response(status, result):\n        \"\"\"Build a json response object.\"\"\"\n        return web.Response(text=json.dumps(result), status=status)\n\n    def web_index_handler(self, request):\n        \"\"\"Handle root web request.\"\"\"\n        return self.build_response(200, {\n            \"message\": \"Welcome to the opsdroid API\"})\n\n    def web_stats_handler(self, request):\n        \"\"\"Handle stats request.\"\"\"\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.const import __version__\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Web:\n    \"\"\"Web server for opsdroid.\"\"\"\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(loop=self.opsdroid.eventloop)\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        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        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        try:\n            ssl_config = self.config[\"ssl\"]\n            sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\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    def start(self):\n        \"\"\"Start web servers.\"\"\"\n        _LOGGER.debug(\n            \"Starting web server with host %s and port %s\",\n            self.get_host, self.get_port)\n        web.run_app(self.web_app, host=self.get_host,\n                    port=self.get_port, print=_LOGGER.info,\n                    ssl_context=self.get_ssl_context)\n\n    @staticmethod\n    def build_response(status, result):\n        \"\"\"Build a json response object.\"\"\"\n        return web.Response(text=json.dumps(result), status=status)\n\n    def web_index_handler(self, request):\n        \"\"\"Handle root web request.\"\"\"\n        return self.build_response(200, {\n            \"message\": \"Welcome to the opsdroid API\"})\n\n    def web_stats_handler(self, request):\n        \"\"\"Handle stats request.\"\"\"\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"}]}