diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 3.0.18
+
+* ForceSSL: preserve port number when redirecting to https. [#582](https://github.com/yesodweb/wai/pull/582)
+
 ## 3.0.17
 
 * Gzip pre compressed [#580](https://github.com/yesodweb/wai/pull/580)
diff --git a/Network/Wai/Middleware/ForceSSL.hs b/Network/Wai/Middleware/ForceSSL.hs
--- a/Network/Wai/Middleware/ForceSSL.hs
+++ b/Network/Wai/Middleware/ForceSSL.hs
@@ -17,7 +17,6 @@
 import Data.Monoid ((<>))
 import Network.HTTP.Types (hLocation, methodGet, status301, status307)
 
-import qualified Data.ByteString as S
 import Data.Word8 (_colon)
 
 -- | For requests that don't appear secure, redirect to https
@@ -31,13 +30,10 @@
 
 redirectResponse :: Request -> Maybe Response
 redirectResponse req = do
-    (host, _) <- S.break (== _colon) <$> requestHeaderHost req
-
-    return $ responseBuilder status [(hLocation, location host)] mempty
-
+  host <- requestHeaderHost req
+  return $ responseBuilder status [(hLocation, location host)] mempty
   where
     location h = "https://" <> h <> rawPathInfo req <> rawQueryString req
-
     status
         | requestMethod req == methodGet = status301
         | otherwise = status307
diff --git a/test/Network/Wai/Middleware/ForceSSLSpec.hs b/test/Network/Wai/Middleware/ForceSSLSpec.hs
--- a/test/Network/Wai/Middleware/ForceSSLSpec.hs
+++ b/test/Network/Wai/Middleware/ForceSSLSpec.hs
@@ -8,6 +8,7 @@
 
 import Network.Wai.Middleware.ForceSSL
 
+import Control.Monad
 import Data.ByteString (ByteString)
 import Data.Monoid ((<>))
 import Network.HTTP.Types (methodPost, status200, status301, status307)
@@ -18,9 +19,13 @@
 main = hspec spec
 
 spec :: Spec
-spec = describe "forceSSL" $ do
-    let host = "example.com"
+spec = describe "forceSSL" (forM_ hosts $ \host -> hostSpec host)
+  where
+    hosts = ["example.com", "example.com:80", "example.com:8080"]
 
+hostSpec :: ByteString -> Spec
+hostSpec host = describe ("forceSSL on host " <> show host <> "") $ do
+
     it "redirects non-https requests to https" $ do
         resp <- runApp host forceSSL defaultRequest
 
@@ -39,7 +44,7 @@
 
         simpleStatus resp `shouldBe` status200
 
-    it "preserves the original path and query string" $ do
+    it "preserves the original host, path, and query string" $ do
         resp <- runApp host forceSSL defaultRequest
             { rawPathInfo = "/foo/bar"
             , rawQueryString = "?baz=bat"
@@ -50,7 +55,6 @@
 
 runApp :: ByteString -> Middleware -> Request -> IO SResponse
 runApp host mw req = runSession
-    (request req { requestHeaderHost = Just $ host <> ":80" }) $ mw app
-
+    (request req { requestHeaderHost = Just host }) $ mw app
   where
     app _ respond = respond $ responseLBS status200 [] ""
diff --git a/wai-extra.cabal b/wai-extra.cabal
--- a/wai-extra.cabal
+++ b/wai-extra.cabal
@@ -1,5 +1,5 @@
 Name:                wai-extra
-Version:             3.0.17
+Version:             3.0.18
 Synopsis:            Provides some basic WAI handlers and middleware.
 description:
   Provides basic WAI handler and middleware functionality:
