diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,11 @@
+# Changelog for http-client
+
+## 0.5.14
+
+* Omit port for `getUri` when protocol is `http` and port is `80`, or when
+  protocol is `https` and port is `443`
+* Sending requests with invalid headers now throws InvalidRequestHeader exception
+
 ## 0.5.13.1
 
 * Add a workaround for a cabal bug [haskell-infra/hackage-trustees#165](https://github.com/haskell-infra/hackage-trustees/issues/165)
diff --git a/Network/HTTP/Client/Core.hs b/Network/HTTP/Client/Core.hs
--- a/Network/HTTP/Client/Core.hs
+++ b/Network/HTTP/Client/Core.hs
@@ -17,6 +17,7 @@
 import Network.HTTP.Types
 import Network.HTTP.Client.Manager
 import Network.HTTP.Client.Types
+import Network.HTTP.Client.Headers
 import Network.HTTP.Client.Body
 import Network.HTTP.Client.Request
 import Network.HTTP.Client.Response
@@ -190,6 +191,9 @@
 -- Since 0.1.0
 responseOpen :: Request -> Manager -> IO (Response BodyReader)
 responseOpen inputReq manager' = do
+  case validateHeaders (requestHeaders inputReq) of
+    GoodHeaders -> return ()
+    BadHeaders reason -> throwHttp $ InvalidRequestHeader reason
   (manager, req0) <- getModifiedRequestManager manager' inputReq
   wrapExc req0 $ mWrapException manager req0 $ do
     (req, res) <- go manager (redirectCount req0) req0
diff --git a/Network/HTTP/Client/Headers.hs b/Network/HTTP/Client/Headers.hs
--- a/Network/HTTP/Client/Headers.hs
+++ b/Network/HTTP/Client/Headers.hs
@@ -3,6 +3,8 @@
 {-# LANGUAGE ViewPatterns #-}
 module Network.HTTP.Client.Headers
     ( parseStatusHeaders
+    , validateHeaders
+    , HeadersValidationResult (..)
     ) where
 
 import           Control.Applicative            as A ((<$>), (<*>))
@@ -10,6 +12,9 @@
 import qualified Data.ByteString                as S
 import qualified Data.ByteString.Char8          as S8
 import qualified Data.CaseInsensitive           as CI
+import           Data.Char (ord)
+import           Data.Maybe (mapMaybe)
+import           Data.Monoid
 import           Network.HTTP.Client.Connection
 import           Network.HTTP.Client.Types
 import           System.Timeout                 (timeout)
@@ -94,3 +99,17 @@
         return (CI.mk $! strip key, strip $! S.drop 1 bs2)
 
     strip = S.dropWhile (== charSpace) . fst . S.spanEnd (== charSpace)
+
+data HeadersValidationResult
+    = GoodHeaders
+    | BadHeaders S.ByteString -- contains a message with the reason
+
+validateHeaders :: RequestHeaders -> HeadersValidationResult
+validateHeaders headers =
+    case mapMaybe validateHeader headers of
+        [] -> GoodHeaders
+        reasons -> BadHeaders (S8.unlines reasons)
+    where
+    validateHeader (k, v)
+        | S8.elem '\n' v = Just ("Header " <> CI.original k <> " has newlines")
+        | True = Nothing
diff --git a/Network/HTTP/Client/Request.hs b/Network/HTTP/Client/Request.hs
--- a/Network/HTTP/Client/Request.hs
+++ b/Network/HTTP/Client/Request.hs
@@ -192,7 +192,7 @@
     , uriAuthority = Just URIAuth
         { uriUserInfo = ""
         , uriRegName = S8.unpack $ host req
-        , uriPort = ':' : show (port req)
+        , uriPort = port'
         }
     , uriPath = S8.unpack $ path req
     , uriQuery =
@@ -201,6 +201,11 @@
             _ -> S8.unpack $ queryString req
     , uriFragment = ""
     }
+  where
+    port'
+      | secure req && (port req) == 443 = ""
+      | not (secure req) && (port req) == 80 = ""
+      | otherwise = ':' : show (port req)
 
 applyAnyUriBasedAuth :: URI -> Request -> Request
 applyAnyUriBasedAuth uri req =
diff --git a/Network/HTTP/Client/Types.hs b/Network/HTTP/Client/Types.hs
--- a/Network/HTTP/Client/Types.hs
+++ b/Network/HTTP/Client/Types.hs
@@ -168,6 +168,10 @@
                    -- ^ The given response header line could not be parsed
                    --
                    -- @since 0.5.0
+                   | InvalidRequestHeader S.ByteString
+                   -- ^ The given request header is not compliant (e.g. has newlines)
+                   --
+                   -- @since 0.5.14
                    | InternalException SomeException
                    -- ^ An exception was raised by an underlying library when
                    -- performing the request. Most often, this is caused by a
diff --git a/http-client.cabal b/http-client.cabal
--- a/http-client.cabal
+++ b/http-client.cabal
@@ -1,5 +1,5 @@
 name:                http-client
-version:             0.5.13.1
+version:             0.5.14
 synopsis:            An HTTP client engine
 description:         Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/http-client>.
 homepage:            https://github.com/snoyberg/http-client
diff --git a/test-nonet/Network/HTTP/Client/RequestSpec.hs b/test-nonet/Network/HTTP/Client/RequestSpec.hs
--- a/test-nonet/Network/HTTP/Client/RequestSpec.hs
+++ b/test-nonet/Network/HTTP/Client/RequestSpec.hs
@@ -54,6 +54,25 @@
         field `shouldSatisfy` isJust
         field `shouldBe` Just "Basic dXNlcjpwYXNz"
 
+    describe "getUri" $ do
+      context "when protocol is http and port is 80" $ do
+        it "omits port" $ do
+          let url = "http://example.com/"
+          request <- parseRequest url
+          show (getUri request) `shouldBe` url
+
+      context "when protocol is https and port is 443" $ do
+        it "omits port" $ do
+          let url = "https://example.com/"
+          request <- parseRequest url
+          show (getUri request) `shouldBe` url
+
+      context "when protocol is https and port is 80" $ do
+        it "does not omit port" $ do
+          let url = "https://example.com:80/"
+          request <- parseRequest url
+          show (getUri request) `shouldBe` url
+
     describe "Show Request" $
       it "redacts authorization header content" $ do
         let request = defaultRequest { requestHeaders = [("Authorization", "secret")] }
