diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # ChangeLog for warp
 
+## 3.4.12
+
+* Respond with `Connection: close` header if connection is to be closed after a request.
+   [#958](https://github.com/yesodweb/wai/pull/958)
+
 ## 3.4.11
 
 * Expose a way to access the open connection `Counter` with `makeSettingsAndCounter`,
diff --git a/Network/Wai/Handler/Warp/Response.hs b/Network/Wai/Handler/Warp/Response.hs
--- a/Network/Wai/Handler/Warp/Response.hs
+++ b/Network/Wai/Handler/Warp/Response.hs
@@ -120,7 +120,7 @@
     -> IO Bool
     -- ^ Returing True if the connection is persistent.
 sendResponse settings conn ii th req reqidxhdr src response = do
-    hs <- addAltSvc settings <$> addServerAndDate hs0
+    hs <- addConnection . addAltSvc settings <$> addServerAndDate hs0
     if hasBody s
         then do
             -- The response to HEAD does not have body.
@@ -148,6 +148,9 @@
     s = responseStatus response
     hs0 = sanitizeHeaders $ responseHeaders response
     rspidxhdr = indexResponseHeader hs0
+    addConnection hs = if (hasBody s && not ret) || (not (hasBody s) && not isPersist)
+                       then (H.hConnection, "close") : hs
+                       else hs
     getdate = getDate ii
     addServerAndDate = addDate getdate rspidxhdr . addServer defServer rspidxhdr
     (isPersist, isChunked0) = infoFromRequest req reqidxhdr
diff --git a/test/ConnectionSpec.hs b/test/ConnectionSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/ConnectionSpec.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module ConnectionSpec (spec) where
+
+import Network.HTTP.Types
+import Network.Wai
+import Network.Wai.Handler.Warp
+import RunSpec (withApp, withMySocket, msWrite, msRead)
+import Test.Hspec
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as S8
+
+spec :: Spec
+spec = describe "Connection header" $ do
+        it "sends Connection: close when response implies close (HTTP/1.0 Keep-Alive, no Content-Length)" $ do
+            let app _ f = f $ responseLBS status200 [] "foo"
+            withApp defaultSettings app $ withMySocket $ \ms -> do
+                -- HTTP/1.0 defaults to close. We ask for Keep-Alive.
+                -- But we provide no Content-Length in response.
+                -- So Warp should decide to close (because it can't keep alive without length or chunking),
+                -- and MUST send "Connection: close" to inform the client.
+                msWrite ms "GET / HTTP/1.0\r\nConnection: Keep-Alive\r\n\r\n"
+                
+                -- We expect the connection to be closed by the server, so reading a large amount 
+                -- should return whatever was sent and then finish.
+                response <- msRead ms 4096
+                
+                let headers = parseHeaders response
+                lookup "Connection" headers `shouldBe` Just "close"
+    
+        describe "HTTP/1.1 Connection: close behavior" $ do
+            it "sends Connection: close for HEAD request without Content-Length" $ do
+                -- Response has no Content-Length and is not chunked (HEAD implies no body).
+                -- In HTTP/1.1 this requires closing the connection to delimit the response (or rather, lack of persistence info).
+                let app _ f = f $ responseBuilder status200 [] "foo"
+                withApp defaultSettings app $ withMySocket $ \ms -> do
+                    msWrite ms "HEAD / HTTP/1.1\r\nHost: localhost\r\n\r\n"
+                    response <- msRead ms 4096
+                    let headers = parseHeaders response
+                    lookup "Connection" headers `shouldBe` Just "close"
+    
+            it "sends Connection: close when request has Connection: close (200 OK)" $ do
+                let app _ f = f $ responseLBS status200 [] "foo"
+                withApp defaultSettings app $ withMySocket $ \ms -> do
+                    msWrite ms "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
+                    response <- msRead ms 4096
+                    let headers = parseHeaders response
+                    lookup "Connection" headers `shouldBe` Just "close"
+    
+            it "sends Connection: close when request has Connection: close (204 No Content)" $ do
+                let app _ f = f $ responseLBS status204 [] ""
+                withApp defaultSettings app $ withMySocket $ \ms -> do
+                    msWrite ms "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
+                    response <- msRead ms 4096
+                    let headers = parseHeaders response
+                    lookup "Connection" headers `shouldBe` Just "close"
+    
+            it "sends Connection: close when request has Connection: close (500 Internal Server Error)" $ do
+                let app _ f = f $ responseLBS status500 [] "error"
+                withApp defaultSettings app $ withMySocket $ \ms -> do
+                    msWrite ms "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
+                    response <- msRead ms 4096
+                    let headers = parseHeaders response
+                    lookup "Connection" headers `shouldBe` Just "close"
+parseHeaders :: ByteString -> [(ByteString, ByteString)]
+parseHeaders bs = 
+    let lines = S8.lines bs
+        -- Drop status line
+        headerLines = takeWhile (not . S8.null . S8.filter (/= '\r')) $ drop 1 lines
+        parseLine line = 
+            let (k, v) = S8.break (== ':') line
+                v' = S8.takeWhile (/= '\r') v
+            in (k, S8.dropWhile (== ' ') $ S8.drop 1 v')
+    in map parseLine headerLines
diff --git a/warp.cabal b/warp.cabal
--- a/warp.cabal
+++ b/warp.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               warp
-version:            3.4.11
+version:            3.4.12
 license:            MIT
 license-file:       LICENSE
 maintainer:         michael@snoyman.com
@@ -114,7 +114,7 @@
         stm >=2.3,
         streaming-commons >=0.1.10,
         text,
-        time-manager >=0.2 && <0.3,
+        time-manager >=0.2 && <0.4,
         vault >=0.3,
         wai >=3.2.4 && <3.3,
         word8
@@ -179,6 +179,7 @@
     hs-source-dirs:     test .
     other-modules:
         ConduitSpec
+        ConnectionSpec
         ExceptionSpec
         FdCacheSpec
         FileSpec
