Update aiohttp to 2.3.1
diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py
index c9de284067fdf2..0a7bd3b7b79e35 100644
--- a/homeassistant/components/http/__init__.py
+++ b/homeassistant/components/http/__init__.py
@@ -181,8 +181,6 @@ def __init__(self, hass, development, api_password, ssl_certificate,
                  use_x_forwarded_for, trusted_networks,
                  login_threshold, is_ban_enabled):
         """Initialize the WSGI Home Assistant server."""
-        import aiohttp_cors
-
         middlewares = [auth_middleware, staticresource_middleware]
 
         if is_ban_enabled:
@@ -207,6 +205,8 @@ def __init__(self, hass, development, api_password, ssl_certificate,
         self.server = None
 
         if cors_origins:
+            import aiohttp_cors
+
             self.cors = aiohttp_cors.setup(self.app, defaults={
                 host: aiohttp_cors.ResourceOptions(
                     allow_headers=ALLOWED_CORS_HEADERS,
@@ -336,7 +336,9 @@ def start(self):
             _LOGGER.error("Failed to create HTTP server at port %d: %s",
                           self.server_port, error)
 
-        self.app._frozen = False  # pylint: disable=protected-access
+        # pylint: disable=protected-access
+        self.app._middlewares = tuple(self.app._prepare_middleware())
+        self.app._frozen = False
 
     @asyncio.coroutine
     def stop(self):
@@ -346,7 +348,7 @@ def stop(self):
             yield from self.server.wait_closed()
         yield from self.app.shutdown()
         if self._handler:
-            yield from self._handler.finish_connections(60.0)
+            yield from self._handler.shutdown(10)
         yield from self.app.cleanup()
 
 
diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py
index 4b971c883d3dd6..ce5bfca3ac1851 100644
--- a/homeassistant/components/http/auth.py
+++ b/homeassistant/components/http/auth.py
@@ -5,6 +5,7 @@
 import logging
 
 from aiohttp import hdrs
+from aiohttp.web import middleware
 
 from homeassistant.const import HTTP_HEADER_HA_AUTH
 from .util import get_real_ip
@@ -15,47 +16,37 @@
 _LOGGER = logging.getLogger(__name__)
 
 
+@middleware
 @asyncio.coroutine
-def auth_middleware(app, handler):
+def auth_middleware(request, handler):
     """Authenticate as middleware."""
     # If no password set, just always set authenticated=True
-    if app['hass'].http.api_password is None:
-        @asyncio.coroutine
-        def no_auth_middleware_handler(request):
-            """Auth middleware to approve all requests."""
-            request[KEY_AUTHENTICATED] = True
-            return handler(request)
-
-        return no_auth_middleware_handler
-
-    @asyncio.coroutine
-    def auth_middleware_handler(request):
-        """Auth middleware to check authentication."""
-        # Auth code verbose on purpose
-        authenticated = False
-
-        if (HTTP_HEADER_HA_AUTH in request.headers and
-                validate_password(
-                    request, request.headers[HTTP_HEADER_HA_AUTH])):
-            # A valid auth header has been set
-            authenticated = True
+    if request.app['hass'].http.api_password is None:
+        request[KEY_AUTHENTICATED] = True
+        return handler(request)
 
-        elif (DATA_API_PASSWORD in request.query and
-              validate_password(request, request.query[DATA_API_PASSWORD])):
-            authenticated = True
+    # Check authentication
+    authenticated = False
 
-        elif (hdrs.AUTHORIZATION in request.headers and
-              validate_authorization_header(request)):
-            authenticated = True
+    if (HTTP_HEADER_HA_AUTH in request.headers and
+            validate_password(
+                request, request.headers[HTTP_HEADER_HA_AUTH])):
+        # A valid auth header has been set
+        authenticated = True
 
-        elif is_trusted_ip(request):
-            authenticated = True
+    elif (DATA_API_PASSWORD in request.query and
+          validate_password(request, request.query[DATA_API_PASSWORD])):
+        authenticated = True
 
-        request[KEY_AUTHENTICATED] = authenticated
+    elif (hdrs.AUTHORIZATION in request.headers and
+          validate_authorization_header(request)):
+        authenticated = True
 
-        return handler(request)
+    elif is_trusted_ip(request):
+        authenticated = True
 
-    return auth_middleware_handler
+    request[KEY_AUTHENTICATED] = authenticated
+    return handler(request)
 
 
 def is_trusted_ip(request):
diff --git a/homeassistant/components/http/ban.py b/homeassistant/components/http/ban.py
index aa01ccde8d763c..f636ad80c36e67 100644
--- a/homeassistant/components/http/ban.py
+++ b/homeassistant/components/http/ban.py
@@ -6,6 +6,7 @@
 import logging
 import os
 
+from aiohttp.web import middleware
 from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
 import voluptuous as vol
 
@@ -32,35 +33,32 @@
 })
 
 
+@middleware
 @asyncio.coroutine
-def ban_middleware(app, handler):
+def ban_middleware(request, handler):
     """IP Ban middleware."""
-    if not app[KEY_BANS_ENABLED]:
-        return handler
+    if not request.app[KEY_BANS_ENABLED]:
+        return (yield from handler(request))
 
-    if KEY_BANNED_IPS not in app:
-        hass = app['hass']
-        app[KEY_BANNED_IPS] = yield from hass.async_add_job(
+    if KEY_BANNED_IPS not in request.app:
+        hass = request.app['hass']
+        request.app[KEY_BANNED_IPS] = yield from hass.async_add_job(
             load_ip_bans_config, hass.config.path(IP_BANS_FILE))
 
-    @asyncio.coroutine
-    def ban_middleware_handler(request):
-        """Verify if IP is not banned."""
-        ip_address_ = get_real_ip(request)
-
-        is_banned = any(ip_ban.ip_address == ip_address_
-                        for ip_ban in request.app[KEY_BANNED_IPS])
+    # Verify if IP is not banned
+    ip_address_ = get_real_ip(request)
 
-        if is_banned:
-            raise HTTPForbidden()
+    is_banned = any(ip_ban.ip_address == ip_address_
+                    for ip_ban in request.app[KEY_BANNED_IPS])
 
-        try:
-            return (yield from handler(request))
-        except HTTPUnauthorized:
-            yield from process_wrong_login(request)
-            raise
+    if is_banned:
+        raise HTTPForbidden()
 
-    return ban_middleware_handler
+    try:
+        return (yield from handler(request))
+    except HTTPUnauthorized:
+        yield from process_wrong_login(request)
+        raise
 
 
 @asyncio.coroutine
diff --git a/homeassistant/components/http/static.py b/homeassistant/components/http/static.py
index 21e955fc9686ef..7ff8b2420426a6 100644
--- a/homeassistant/components/http/static.py
+++ b/homeassistant/components/http/static.py
@@ -3,7 +3,7 @@
 import re
 
 from aiohttp import hdrs
-from aiohttp.web import FileResponse
+from aiohttp.web import FileResponse, middleware
 from aiohttp.web_exceptions import HTTPNotFound
 from aiohttp.web_urldispatcher import StaticResource
 from yarl import unquote
@@ -64,21 +64,17 @@ def sendfile(request, fobj, count):
         self._sendfile = sendfile
 
 
+@middleware
 @asyncio.coroutine
-def staticresource_middleware(app, handler):
+def staticresource_middleware(request, handler):
     """Middleware to strip out fingerprint from fingerprinted assets."""
-    @asyncio.coroutine
-    def static_middleware_handler(request):
-        """Strip out fingerprints from resource names."""
-        if not request.path.startswith('/static/'):
-            return handler(request)
-
-        fingerprinted = _FINGERPRINT.match(request.match_info['filename'])
+    if not request.path.startswith('/static/'):
+        return handler(request)
 
-        if fingerprinted:
-            request.match_info['filename'] = \
-                '{}.{}'.format(*fingerprinted.groups())
+    fingerprinted = _FINGERPRINT.match(request.match_info['filename'])
 
-        return handler(request)
+    if fingerprinted:
+        request.match_info['filename'] = \
+            '{}.{}'.format(*fingerprinted.groups())
 
-    return static_middleware_handler
+    return handler(request)
diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt
index 7da871606845ab..00df81290e5b14 100644
--- a/homeassistant/package_constraints.txt
+++ b/homeassistant/package_constraints.txt
@@ -5,7 +5,7 @@ pip>=8.0.3
 jinja2>=2.9.6
 voluptuous==0.10.5
 typing>=3,<4
-aiohttp==2.2.5
+aiohttp==2.3.1
 async_timeout==2.0.0
 chardet==3.0.4
 astral==1.4
diff --git a/requirements_all.txt b/requirements_all.txt
index 3d899ecbee7aee..2f0e7f8e1adeeb 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -6,7 +6,7 @@ pip>=8.0.3
 jinja2>=2.9.6
 voluptuous==0.10.5
 typing>=3,<4
-aiohttp==2.2.5
+aiohttp==2.3.1
 async_timeout==2.0.0
 chardet==3.0.4
 astral==1.4
diff --git a/setup.py b/setup.py
index cd7043650ad245..74ce4c4d2e3bd3 100755
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@
     'jinja2>=2.9.6',
     'voluptuous==0.10.5',
     'typing>=3,<4',
-    'aiohttp==2.2.5',
+    'aiohttp==2.3.1',
     'async_timeout==2.0.0',
     'chardet==3.0.4',
     'astral==1.4',
diff --git a/tests/components/http/test_init.py b/tests/components/http/test_init.py
index 4428b5043fdd4f..95c192b47e2232 100644
--- a/tests/components/http/test_init.py
+++ b/tests/components/http/test_init.py
@@ -139,22 +139,10 @@ def test_registering_view_while_running(hass, test_client):
         }
     )
 
-    yield from setup.async_setup_component(hass, 'api')
-
     yield from hass.async_start()
-
-    yield from hass.async_block_till_done()
-
+    # This raises a RuntimeError if app is frozen
     hass.http.register_view(TestView)
 
-    client = yield from test_client(hass.http.app)
-
-    resp = yield from client.get('/hello')
-    assert resp.status == 200
-
-    text = yield from resp.text()
-    assert text == 'hello'
-
 
 @asyncio.coroutine
 def test_api_base_url_with_domain(hass):

## Description:

Update aiohttp to version 2.3.1
http://aiohttp.readthedocs.io/en/stable/changes.html

If the code does not interact with devices:
  - [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
  - [ ] Tests have been added to verify that the new code works.

[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L14
[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L54
