diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,34 @@
+## Req 3.13.4
+
+* Fixed empty ciphersuite list when compiling against `tls < 2.0.6`
+  (see [PR 175](https://github.com/mrkkrp/req/pull/175)). As a side effect, now
+  compatible with older versions of `crypton-connection` (>= 0.3).
+
+## Req 3.13.3
+
+* Works with `crypton-connection-0.4` and newer.
+
+## Req 3.13.2
+
+* Disable the problematic `httpbin-tests` test suite by default. Only enable
+  it when the `dev` flag is enabled. In that case it is expected that an
+  httpbin server is run locally at `localhost:1234`.
+
+## Req 3.13.1
+
+* Switched the non-pure test suite to use https://httpbun.org instead of
+  https://httpbin.org since the latter proved to be highly unreliable
+  lately.
+
+* Switched from `connection` to `crypton-connection`.
+
+* Builds with GHC 9.6.1.
+
+## Req 3.13.0
+
+* Add `headerRedacted` function to add header fields, which will be with
+  redacted values on print.
+
 ## Req 3.12.0
 
 * Add `isStatusCodeException` function.
diff --git a/Network/HTTP/Req.hs b/Network/HTTP/Req.hs
--- a/Network/HTTP/Req.hs
+++ b/Network/HTTP/Req.hs
@@ -1,20 +1,9 @@
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveLift #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
-{-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE RoleAnnotations #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TemplateHaskellQuotes #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
@@ -161,6 +150,7 @@
     -- *** Headers
     header,
     attachHeader,
+    headerRedacted,
 
     -- *** Cookies
     -- $cookies
@@ -213,69 +203,72 @@
   )
 where
 
-import qualified Blaze.ByteString.Builder as BB
+import Blaze.ByteString.Builder qualified as BB
 import Control.Applicative
 import Control.Arrow (first, second)
 import Control.Exception hiding (Handler (..), TypeError)
+import Control.Monad (guard, void, (>=>))
 import Control.Monad.Base
 import Control.Monad.Catch (Handler (..), MonadCatch, MonadMask, MonadThrow)
 import Control.Monad.IO.Class
 import Control.Monad.IO.Unlift
-import Control.Monad.Reader
+import Control.Monad.Reader (ReaderT (ReaderT), ask, lift, runReaderT)
 import Control.Monad.Trans.Accum (AccumT)
 import Control.Monad.Trans.Cont (ContT)
 import Control.Monad.Trans.Control
 import Control.Monad.Trans.Except (ExceptT)
 import Control.Monad.Trans.Identity (IdentityT)
 import Control.Monad.Trans.Maybe (MaybeT)
-import qualified Control.Monad.Trans.RWS.CPS as RWS.CPS
-import qualified Control.Monad.Trans.RWS.Lazy as RWS.Lazy
-import qualified Control.Monad.Trans.RWS.Strict as RWS.Strict
+import Control.Monad.Trans.RWS.CPS qualified as RWS.CPS
+import Control.Monad.Trans.RWS.Lazy qualified as RWS.Lazy
+import Control.Monad.Trans.RWS.Strict qualified as RWS.Strict
 import Control.Monad.Trans.Select (SelectT)
-import qualified Control.Monad.Trans.State.Lazy as State.Lazy
-import qualified Control.Monad.Trans.State.Strict as State.Strict
-import qualified Control.Monad.Trans.Writer.CPS as Writer.CPS
-import qualified Control.Monad.Trans.Writer.Lazy as Writer.Lazy
-import qualified Control.Monad.Trans.Writer.Strict as Writer.Strict
+import Control.Monad.Trans.State.Lazy qualified as State.Lazy
+import Control.Monad.Trans.State.Strict qualified as State.Strict
+import Control.Monad.Trans.Writer.CPS qualified as Writer.CPS
+import Control.Monad.Trans.Writer.Lazy qualified as Writer.Lazy
+import Control.Monad.Trans.Writer.Strict qualified as Writer.Strict
 import Control.Retry
 import Data.Aeson (FromJSON (..), ToJSON (..))
-import qualified Data.Aeson as A
+import Data.Aeson qualified as A
 import Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.CaseInsensitive as CI
+import Data.ByteString qualified as B
+import Data.ByteString.Lazy qualified as BL
+import Data.CaseInsensitive qualified as CI
 import Data.Data (Data)
+import Data.Default.Class (def)
 import Data.Function (on)
 import Data.IORef
 import Data.Kind (Constraint, Type)
 import Data.List (foldl', nubBy)
 import Data.List.NonEmpty (NonEmpty (..))
-import qualified Data.List.NonEmpty as NE
+import Data.List.NonEmpty qualified as NE
 import Data.Maybe (fromMaybe)
 import Data.Proxy
 import Data.Semigroup (Endo (..))
+import Data.Set qualified as S
 import Data.Text (Text)
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
+import Data.Text qualified as T
+import Data.Text.Encoding qualified as T
 import Data.Typeable (Typeable, cast)
 import GHC.Generics
 import GHC.TypeLits
-import qualified Language.Haskell.TH as TH
-import qualified Language.Haskell.TH.Quote as TH
-import qualified Language.Haskell.TH.Syntax as TH
-import qualified Network.Connection as NC
-import qualified Network.HTTP.Client as L
-import qualified Network.HTTP.Client.Internal as LI
-import qualified Network.HTTP.Client.MultipartFormData as LM
-import qualified Network.HTTP.Client.TLS as L
-import qualified Network.HTTP.Types as Y
+import Language.Haskell.TH qualified as TH
+import Language.Haskell.TH.Quote qualified as TH
+import Language.Haskell.TH.Syntax qualified as TH
+import Network.Connection qualified as NC
+import Network.HTTP.Client qualified as L
+import Network.HTTP.Client.Internal qualified as LI
+import Network.HTTP.Client.MultipartFormData qualified as LM
+import Network.HTTP.Client.TLS qualified as L
+import Network.HTTP.Types qualified as Y
 import System.IO.Unsafe (unsafePerformIO)
 import Text.URI (URI)
-import qualified Text.URI as URI
-import qualified Text.URI.QQ as QQ
-import qualified Web.Authenticate.OAuth as OAuth
+import Text.URI qualified as URI
+import Text.URI.QQ qualified as QQ
+import Web.Authenticate.OAuth qualified as OAuth
 import Web.FormUrlEncoded (FromForm (..), ToForm (..))
-import qualified Web.FormUrlEncoded as Form
+import Web.FormUrlEncoded qualified as Form
 import Web.HttpApiData (ToHttpApiData (..))
 
 ----------------------------------------------------------------------------
@@ -496,7 +489,7 @@
 --
 -- @since 3.7.0
 reqHandler ::
-  MonadHttp m =>
+  (MonadHttp m) =>
   -- | How to get final result from a 'L.Response'
   (L.Response L.BodyReader -> IO b) ->
   -- | 'L.Request' to perform
@@ -594,7 +587,7 @@
 -- | Perform an action using the global implicit 'L.Manager' that the rest
 -- of the library uses. This allows to reuse connections that the
 -- 'L.Manager' controls.
-withReqManager :: MonadIO m => (L.Manager -> m a) -> m a
+withReqManager :: (MonadIO m) => (L.Manager -> m a) -> m a
 withReqManager m = liftIO (readIORef globalManager) >>= m
 
 -- | The global 'L.Manager' that 'req' uses. Here we just go with the
@@ -614,7 +607,7 @@
   let settings =
         L.mkManagerSettingsContext
           (Just context)
-          (NC.TLSSettingsSimple False False False)
+          def
           Nothing
   manager <- L.newManager settings
   newIORef manager
@@ -637,7 +630,7 @@
 -- | A type class for monads that support performing HTTP requests.
 -- Typically, you only need to define the 'handleHttpException' method
 -- unless you want to tweak 'HttpConfig'.
-class MonadIO m => MonadHttp m where
+class (MonadIO m) => MonadHttp m where
   -- | This method describes how to deal with 'HttpException' that was
   -- caught by the library. One option is to re-throw it if you are OK with
   -- exceptions, but if you prefer working with something like
@@ -721,7 +714,7 @@
     -- | Max length of preview fragment of response body.
     --
     -- @since 3.6.0
-    httpConfigBodyPreviewLength :: forall a. Num a => a
+    httpConfigBodyPreviewLength :: forall a. (Num a) => a
   }
   deriving (Typeable)
 
@@ -811,27 +804,27 @@
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (ContT r m) where
+instance (MonadHttp m) => MonadHttp (ContT r m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (ExceptT e m) where
+instance (MonadHttp m) => MonadHttp (ExceptT e m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (IdentityT m) where
+instance (MonadHttp m) => MonadHttp (IdentityT m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (MaybeT m) where
+instance (MonadHttp m) => MonadHttp (MaybeT m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (ReaderT r m) where
+instance (MonadHttp m) => MonadHttp (ReaderT r m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
@@ -851,17 +844,17 @@
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (SelectT r m) where
+instance (MonadHttp m) => MonadHttp (SelectT r m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (State.Lazy.StateT s m) where
+instance (MonadHttp m) => MonadHttp (State.Lazy.StateT s m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
 -- | @since 3.10.0
-instance MonadHttp m => MonadHttp (State.Strict.StateT s m) where
+instance (MonadHttp m) => MonadHttp (State.Strict.StateT s m) where
   handleHttpException = lift . handleHttpException
   getHttpConfig = lift getHttpConfig
 
@@ -885,7 +878,7 @@
 --
 -- @since 0.4.0
 runReq ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | 'HttpConfig' to use
   HttpConfig ->
   -- | Computation to run
@@ -990,7 +983,7 @@
   -- | Return name of the method as a 'ByteString'.
   httpMethodName :: Proxy a -> ByteString
 
-instance HttpMethod method => RequestComponent (Tagged "method" method) where
+instance (HttpMethod method) => RequestComponent (Tagged "method" method) where
   getRequestMod _ = Endo $ \x ->
     x {L.method = httpMethodName (Proxy :: Proxy method)}
 
@@ -1038,19 +1031,14 @@
 
 -- With template-haskell >=2.15 and text >=1.2.4 Lift can be derived, however
 -- the derived lift forgets the type of the scheme.
-instance Typeable scheme => TH.Lift (Url scheme) where
+instance (Typeable scheme) => TH.Lift (Url scheme) where
   lift url =
     TH.dataToExpQ (fmap liftText . cast) url `TH.sigE` case url of
       Url Http _ -> [t|Url 'Http|]
       Url Https _ -> [t|Url 'Https|]
     where
       liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)
-
-#if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
-#elif MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = TH.unsafeTExpCoerce . TH.lift
-#endif
 
 -- | Given host name, produce a 'Url' which has “http” as its scheme and
 -- empty path. This also sets port to @80@.
@@ -1066,7 +1054,7 @@
 -- path segment can be of any type that is an instance of 'ToHttpApiData'.
 infixl 5 /~
 
-(/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme
+(/~) :: (ToHttpApiData a) => Url scheme -> a -> Url scheme
 Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
 
 -- | A type-constrained version of @('/~')@ to remove ambiguity in the cases
@@ -1254,7 +1242,7 @@
 -- charset=utf-8\"@ value.
 newtype ReqBodyJson a = ReqBodyJson a
 
-instance ToJSON a => HttpBody (ReqBodyJson a) where
+instance (ToJSON a) => HttpBody (ReqBodyJson a) where
   getRequestBody (ReqBodyJson a) = L.RequestBodyLBS (A.encode a)
   getRequestContentType _ = pure "application/json; charset=utf-8"
 
@@ -1353,7 +1341,7 @@
 -- | Create 'ReqBodyMultipart' request body from a collection of 'LM.Part's.
 --
 -- @since 0.2.0
-reqBodyMultipart :: MonadIO m => [LM.Part] -> m ReqBodyMultipart
+reqBodyMultipart :: (MonadIO m) => [LM.Part] -> m ReqBodyMultipart
 reqBodyMultipart parts = liftIO $ do
   boundary <- LM.webkitBoundary
   body <- LM.renderParts boundary parts
@@ -1393,7 +1381,7 @@
     TypeError
       ('Text "This HTTP method does not allow attaching a request body.")
 
-instance HttpBody body => RequestComponent (Tagged "body" body) where
+instance (HttpBody body) => RequestComponent (Tagged "body" body) where
   getRequestMod (Tagged body) = Endo $ \x ->
     x
       { L.requestBody = getRequestBody body,
@@ -1463,7 +1451,7 @@
 
 -- | Finalize given 'L.Request' by applying a finalizer from the given
 -- 'Option' (if it has any).
-finalizeRequest :: MonadIO m => Option scheme -> L.Request -> m L.Request
+finalizeRequest :: (MonadIO m) => Option scheme -> L.Request -> m L.Request
 finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
 
 ----------------------------------------------------------------------------
@@ -1496,7 +1484,7 @@
 -- This operator is defined in terms of 'queryParam':
 --
 -- > queryFlag name = queryParam name (Nothing :: Maybe ())
-queryFlag :: QueryParam param => Text -> param
+queryFlag :: (QueryParam param) => Text -> param
 queryFlag name = queryParam name (Nothing :: Maybe ())
 
 -- | Construct query parameters from a 'ToForm' instance. This function
@@ -1526,7 +1514,7 @@
   -- 'Nothing', it won't be included at all (i.e. you create a flag this
   -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
   -- method, because they are easier to read.
-  queryParam :: ToHttpApiData a => Text -> Maybe a -> param
+  queryParam :: (ToHttpApiData a) => Text -> Maybe a -> param
 
   -- | Get the query parameter names and values set by 'queryParam'.
   --
@@ -1560,6 +1548,14 @@
 attachHeader name value x =
   x {L.requestHeaders = (CI.mk name, value) : L.requestHeaders x}
 
+-- | Same as 'header', but with redacted values on print.
+--
+-- @since 3.13.0
+headerRedacted :: ByteString -> ByteString -> Option scheme
+headerRedacted name value = withRequest $ \x ->
+  let y = attachHeader name value x
+   in y {L.redactHeaders = CI.mk name `S.insert` L.redactHeaders y}
+
 ----------------------------------------------------------------------------
 -- Request—Optional parameters—Cookies
 
@@ -1767,7 +1763,7 @@
 newtype JsonResponse a = JsonResponse (L.Response a)
   deriving (Show)
 
-instance FromJSON a => HttpResponse (JsonResponse a) where
+instance (FromJSON a) => HttpResponse (JsonResponse a) where
   type HttpResponseBody (JsonResponse a) = a
   toVanillaResponse (JsonResponse r) = r
   getHttpResponse r = do
@@ -1883,14 +1879,14 @@
 
 -- | Get the response body.
 responseBody ::
-  HttpResponse response =>
+  (HttpResponse response) =>
   response ->
   HttpResponseBody response
 responseBody = L.responseBody . toVanillaResponse
 
 -- | Get the response status code.
 responseStatusCode ::
-  HttpResponse response =>
+  (HttpResponse response) =>
   response ->
   Int
 responseStatusCode =
@@ -1898,7 +1894,7 @@
 
 -- | Get the response status message.
 responseStatusMessage ::
-  HttpResponse response =>
+  (HttpResponse response) =>
   response ->
   ByteString
 responseStatusMessage =
@@ -1906,7 +1902,7 @@
 
 -- | Lookup a particular header from a response.
 responseHeader ::
-  HttpResponse response =>
+  (HttpResponse response) =>
   -- | Response interpretation
   response ->
   -- | Header to lookup
@@ -1918,7 +1914,7 @@
 
 -- | Get the response 'L.CookieJar'.
 responseCookieJar ::
-  HttpResponse response =>
+  (HttpResponse response) =>
   response ->
   L.CookieJar
 responseCookieJar = L.responseCookieJar . toVanillaResponse
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Main (main) where
-
-import Distribution.Simple
-
-main :: IO ()
-main = defaultMain
diff --git a/httpbin-tests/Network/HTTP/ReqSpec.hs b/httpbin-tests/Network/HTTP/ReqSpec.hs
--- a/httpbin-tests/Network/HTTP/ReqSpec.hs
+++ b/httpbin-tests/Network/HTTP/ReqSpec.hs
@@ -8,24 +8,25 @@
 module Network.HTTP.ReqSpec (spec) where
 
 import Control.Exception
-import Control.Monad.Reader
+import Control.Monad (forM_)
 import Control.Monad.Trans.Control
 import Data.Aeson (ToJSON (..), Value (..), object, (.=))
-import qualified Data.Aeson as A
-import qualified Data.Aeson.KeyMap as Aeson.KeyMap
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
+import Data.Aeson qualified as A
+import Data.Aeson.KeyMap qualified as Aeson.KeyMap
+import Data.ByteString qualified as B
+import Data.ByteString.Lazy qualified as BL
 import Data.Functor.Identity (runIdentity)
 import Data.Maybe (fromJust)
 import Data.Proxy
 import Data.Text (Text)
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
-import qualified Data.Text.IO as TIO
-import qualified Network.HTTP.Client as L
-import qualified Network.HTTP.Client.MultipartFormData as LM
-import Network.HTTP.Req
-import qualified Network.HTTP.Types as Y
+import Data.Text qualified as T
+import Data.Text.Encoding qualified as T
+import Data.Text.IO qualified as TIO
+import Network.HTTP.Client qualified as L
+import Network.HTTP.Client.MultipartFormData qualified as LM
+import Network.HTTP.Req hiding (req)
+import Network.HTTP.Req qualified as Req
+import Network.HTTP.Types qualified as Y
 import Test.Hspec
 import Test.QuickCheck
 
@@ -84,8 +85,7 @@
               .= object
                 [ "Accept-Encoding" .= ("gzip" :: Text),
                   "Foo" .= ("bar" :: Text),
-                  "Baz" .= ("quux" :: Text),
-                  "Host" .= ("httpbin.org" :: Text)
+                  "Baz" .= ("quux" :: Text)
                 ]
           ]
       responseStatusCode r `shouldBe` 200
@@ -97,11 +97,10 @@
       (stripFunnyHeaders . stripOrigin) (responseBody r)
         `shouldBe` object
           [ "args" .= emptyObject,
-            "url" .= ("https://httpbin.org/get" :: Text),
+            "url" .= ("http://localhost:1234/get" :: Text),
             "headers"
               .= object
-                [ "Accept-Encoding" .= ("gzip" :: Text),
-                  "Host" .= ("httpbin.org" :: Text)
+                [ "Accept-Encoding" .= ("gzip" :: Text)
                 ]
           ]
       responseHeader r "Content-Type" `shouldBe` return "application/json"
@@ -118,12 +117,11 @@
           [ "args" .= emptyObject,
             "json" .= text,
             "data" .= reflected,
-            "url" .= ("https://httpbin.org/post" :: Text),
+            "url" .= ("http://localhost:1234/post" :: Text),
             "headers"
               .= object
                 [ "Content-Type" .= ("application/json; charset=utf-8" :: Text),
                   "Accept-Encoding" .= ("gzip" :: Text),
-                  "Host" .= ("httpbin.org" :: Text),
                   "Content-Length" .= show (T.length reflected)
                 ],
             "files" .= emptyObject,
@@ -147,12 +145,11 @@
           [ "args" .= emptyObject,
             "json" .= Null,
             "data" .= ("" :: Text),
-            "url" .= ("https://httpbin.org/post" :: Text),
+            "url" .= ("http://localhost:1234/post" :: Text),
             "headers"
               .= object
                 [ "Content-Type" .= T.decodeUtf8 contentType,
                   "Accept-Encoding" .= ("gzip" :: Text),
-                  "Host" .= ("httpbin.org" :: Text),
                   "Content-Length" .= ("242" :: Text)
                 ],
             "files" .= emptyObject,
@@ -177,11 +174,10 @@
           [ "args" .= emptyObject,
             "json" .= Null,
             "data" .= contents,
-            "url" .= ("https://httpbin.org/patch" :: Text),
+            "url" .= ("http://localhost:1234/patch" :: Text),
             "headers"
               .= object
                 [ "Accept-Encoding" .= ("gzip" :: Text),
-                  "Host" .= ("httpbin.org" :: Text),
                   "Content-Length" .= show (T.length contents)
                 ],
             "files" .= emptyObject,
@@ -203,12 +199,11 @@
           [ "args" .= emptyObject,
             "json" .= Null,
             "data" .= ("" :: Text),
-            "url" .= ("https://httpbin.org/put" :: Text),
+            "url" .= ("http://localhost:1234/put" :: Text),
             "headers"
               .= object
                 [ "Content-Type" .= ("application/x-www-form-urlencoded" :: Text),
                   "Accept-Encoding" .= ("gzip" :: Text),
-                  "Host" .= ("httpbin.org" :: Text),
                   "Content-Length" .= ("18" :: Text)
                 ],
             "files" .= emptyObject,
@@ -306,7 +301,7 @@
             (httpbin /: "basic-auth" /~ user /~ password)
             NoReqBody
             ignoreResponse
-            (basicAuth (T.encodeUtf8 user) (T.encodeUtf8 password))
+            (basicAuthUnsafe (T.encodeUtf8 user) (T.encodeUtf8 password))
         responseStatusCode r `shouldBe` 200
         responseStatusMessage r `shouldBe` "OK"
 
@@ -406,9 +401,29 @@
     doit _ _ = error "Oops!"
 
 -- | 'Url' representing <https://httpbin.org>.
-httpbin :: Url 'Https
-httpbin = https "httpbin.org"
+httpbin :: Url 'Http
+httpbin = http "localhost"
 
+req ::
+  ( MonadHttp m,
+    HttpMethod method,
+    HttpBody body,
+    HttpResponse response,
+    HttpBodyAllowed (AllowsBody method) (ProvidesBody body)
+  ) =>
+  method ->
+  Url scheme ->
+  body ->
+  Proxy response ->
+  Option scheme ->
+  m response
+req method url body responseProxy options =
+  Req.req method url body responseProxy (options <> defaultOptions)
+
+-- | Options to apply by default.
+defaultOptions :: Option scheme
+defaultOptions = port 1234
+
 -- | Remove “origin” field from JSON value. Origin may change, we don't want
 -- to depend on that.
 stripOrigin :: Value -> Value
@@ -417,20 +432,37 @@
 
 -- | Remove funny headers that might break the tests.
 stripFunnyHeaders :: Value -> Value
-stripFunnyHeaders (Object m) =
-  let f (Object p) = Object $ Aeson.KeyMap.filterWithKey (\k _ -> k `elem` hs) p
-      f value = value
-      hs =
-        [ "Content-Type",
-          "Accept-Encoding",
-          "Host",
-          "Content-Length",
-          "Foo",
-          "Baz"
-        ]
-   in Object (runIdentity (Aeson.KeyMap.alterF (pure . fmap f) "headers" m))
-stripFunnyHeaders value = value
+stripFunnyHeaders = \case
+  Object m ->
+    Object
+      ( runIdentity
+          ( Aeson.KeyMap.alterF
+              (pure . fmap stripFunnyHeaders')
+              "headers"
+              m
+          )
+      )
+  value -> value
 
+-- | Similar to 'stripFunnyHeaders', but acts directly on the argument
+-- without trying to access its "headers" field.
+stripFunnyHeaders' :: Value -> Value
+stripFunnyHeaders' = \case
+  Object p ->
+    Object $
+      Aeson.KeyMap.filterWithKey
+        (\k _ -> k `elem` whitelistedHeaders)
+        p
+  value -> value
+  where
+    whitelistedHeaders =
+      [ "Content-Type",
+        "Accept-Encoding",
+        "Content-Length",
+        "Foo",
+        "Baz"
+      ]
+
 -- | This is a complete test case that makes use of <https://httpbin.org> to
 -- get various response status codes.
 checkStatusCode :: Int -> SpecWith ()
@@ -471,7 +503,7 @@
 emptyObject = Object Aeson.KeyMap.empty
 
 -- | Get a rendered JSON value as 'Text'.
-reflectJSON :: ToJSON a => a -> Text
+reflectJSON :: (ToJSON a) => a -> Text
 reflectJSON = T.decodeUtf8 . BL.toStrict . A.encode
 
 -- | Clarify to the type checker that the inner computation is in the 'IO'
diff --git a/pure-tests/Network/HTTP/ReqSpec.hs b/pure-tests/Network/HTTP/ReqSpec.hs
--- a/pure-tests/Network/HTTP/ReqSpec.hs
+++ b/pure-tests/Network/HTTP/ReqSpec.hs
@@ -13,41 +13,41 @@
 
 module Network.HTTP.ReqSpec (spec) where
 
-import qualified Blaze.ByteString.Builder as BB
+import Blaze.ByteString.Builder qualified as BB
 import Control.Exception (throwIO)
 import Control.Monad
 import Control.Retry
 import Data.Aeson (ToJSON (..))
-import qualified Data.Aeson as A
+import Data.Aeson qualified as A
 import Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as B8
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.CaseInsensitive as CI
+import Data.ByteString qualified as B
+import Data.ByteString.Char8 qualified as B8
+import Data.ByteString.Lazy qualified as BL
+import Data.CaseInsensitive qualified as CI
 import Data.Either (isRight)
-import qualified Data.List.NonEmpty as NE
+import Data.List.NonEmpty qualified as NE
 import Data.Maybe (fromJust, fromMaybe, isJust, isNothing)
 import Data.Proxy
 import Data.Text (Text)
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
+import Data.Text qualified as T
+import Data.Text.Encoding qualified as T
 import Data.Time
 import Data.Typeable (Typeable, eqT)
 import GHC.Exts (IsList (..))
 import GHC.Generics
-import qualified Language.Haskell.TH as TH
-import qualified Language.Haskell.TH.Quote as TH
-import qualified Network.HTTP.Client as L
+import Language.Haskell.TH qualified as TH
+import Language.Haskell.TH.Quote qualified as TH
+import Network.HTTP.Client qualified as L
 import Network.HTTP.Req
-import qualified Network.HTTP.Types as Y
-import qualified Network.HTTP.Types.Header as Y
+import Network.HTTP.Types qualified as Y
+import Network.HTTP.Types.Header qualified as Y
 import Test.Hspec
 import Test.Hspec.Core.Spec (SpecM)
 import Test.QuickCheck
 import Text.URI (URI)
-import qualified Text.URI as URI
-import qualified Text.URI.QQ as QQ
-import qualified Web.FormUrlEncoded as F
+import Text.URI qualified as URI
+import Text.URI.QQ qualified as QQ
+import Web.FormUrlEncoded qualified as F
 
 spec :: Spec
 spec = do
@@ -413,7 +413,7 @@
         -- 'Https, Option _) type checks, so we can catch if the type of scheme
         -- is unspecified.
         let testTypeOfQuoterResult ::
-              forall a s. Typeable a => (a, Option s) -> Bool
+              forall a s. (Typeable a) => (a, Option s) -> Bool
             testTypeOfQuoterResult _ = isJust $ eqT @a @(Url 'Https)
          in property $ testTypeOfQuoterResult [urlQ|https://example.org/|]
       it "doesn't work for invalid urls" $
diff --git a/req.cabal b/req.cabal
--- a/req.cabal
+++ b/req.cabal
@@ -1,11 +1,11 @@
 cabal-version:   2.4
 name:            req
-version:         3.12.0
+version:         3.13.4
 license:         BSD-3-Clause
 license-file:    LICENSE.md
 maintainer:      Mark Karpov <markkarpov92@gmail.com>
 author:          Mark Karpov <markkarpov92@gmail.com>
-tested-with:     ghc ==8.10.7 ghc ==9.0.2 ghc ==9.2.1
+tested-with:     ghc ==9.6.3 ghc ==9.8.2 ghc ==9.10.1
 homepage:        https://github.com/mrkkrp/req
 bug-reports:     https://github.com/mrkkrp/req/issues
 synopsis:        HTTP client library
@@ -31,71 +31,70 @@
 
 library
     exposed-modules:  Network.HTTP.Req
-    default-language: Haskell2010
+    default-language: GHC2021
     build-depends:
         aeson >=0.9 && <3,
         authenticate-oauth >=1.5 && <1.8,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5,
         blaze-builder >=0.3 && <0.5,
-        bytestring >=0.10.8 && <0.12,
+        bytestring >=0.10.8 && <0.13,
         case-insensitive >=0.2 && <1.3,
-        connection >=0.2.2 && <0.4,
+        containers >=0.5 && <0.7,
+        crypton-connection >=0.3 && <0.5,
+        data-default-class,
         exceptions >=0.6 && <0.11,
-        http-api-data >=0.2 && <0.5,
-        http-client >=0.7 && <0.8,
+        http-api-data >=0.2 && <0.7,
+        http-client >=0.7.13.1 && <0.8,
         http-client-tls >=0.3.2 && <0.4,
-        http-types >=0.8 && <10.0,
+        http-types >=0.8 && <10,
         modern-uri >=0.3 && <0.4,
         monad-control >=1.0 && <1.1,
         mtl >=2.0 && <3.0,
         retry >=0.8 && <0.10,
-        template-haskell >=2.14 && <2.19,
-        text >=0.2 && <2.1,
-        time >=1.2 && <1.13,
-        transformers >=0.5.3.0 && <0.6,
+        template-haskell >=2.19 && <2.23,
+        text >=0.2 && <2.2,
+        transformers >=0.5.3.0 && <0.7,
         transformers-base,
         unliftio-core >=0.1.1 && <0.3
 
     if flag(dev)
-        ghc-options: -O0 -Wall -Werror
+        ghc-options:
+            -Wall -Werror -Wpartial-fields -Wunused-packages
+            -Wno-unused-imports
 
     else
         ghc-options: -O2 -Wall
 
-    if flag(dev)
-        ghc-options:
-            -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns
-            -Wnoncanonical-monad-instances
-
 test-suite pure-tests
     type:               exitcode-stdio-1.0
     main-is:            Spec.hs
-    build-tool-depends: hspec-discover:hspec-discover >=2.0 && <3.0
+    build-tool-depends: hspec-discover:hspec-discover >=2 && <3
     hs-source-dirs:     pure-tests
     other-modules:      Network.HTTP.ReqSpec
-    default-language:   Haskell2010
+    default-language:   GHC2021
     build-depends:
-        QuickCheck >=2.7 && <3.0,
+        QuickCheck >=2.7 && <3,
         aeson >=0.9 && <3,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5.0,
         blaze-builder >=0.3 && <0.5,
-        bytestring >=0.10.8 && <0.12,
+        bytestring >=0.10.8 && <0.13,
         case-insensitive >=0.2 && <1.3,
-        hspec >=2.0 && <3.0,
-        hspec-core >=2.0 && <3.0,
-        http-api-data >=0.2 && <0.5,
+        hspec >=2.0 && <3,
+        hspec-core >=2.0 && <3,
+        http-api-data >=0.2 && <0.7,
         http-client >=0.7 && <0.8,
-        http-types >=0.8 && <10.0,
+        http-types >=0.8 && <10,
         modern-uri >=0.3 && <0.4,
-        mtl >=2.0 && <3.0,
         req,
         retry >=0.8 && <0.10,
-        template-haskell >=2.14 && <2.19,
-        text >=0.2 && <2.1,
+        template-haskell >=2.19 && <2.23,
+        text >=0.2 && <2.2,
         time >=1.2 && <1.13
 
     if flag(dev)
-        ghc-options: -O0 -Wall -Werror
+        ghc-options:
+            -Wall -Werror -Wredundant-constraints -Wpartial-fields
+            -Wunused-packages
 
     else
         ghc-options: -O2 -Wall
@@ -103,25 +102,26 @@
 test-suite httpbin-tests
     type:               exitcode-stdio-1.0
     main-is:            Spec.hs
-    build-tool-depends: hspec-discover:hspec-discover >=2.0 && <3.0
+    build-tool-depends: hspec-discover:hspec-discover >=2 && <3
     hs-source-dirs:     httpbin-tests
     other-modules:      Network.HTTP.ReqSpec
-    default-language:   Haskell2010
+    default-language:   GHC2021
     build-depends:
-        QuickCheck >=2.7 && <3.0,
+        QuickCheck >=2.7 && <3,
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
-        bytestring >=0.10.8 && <0.12,
+        base >=4.15 && <5,
+        bytestring >=0.10.8 && <0.13,
         hspec >=2.0 && <3.0,
         http-client >=0.7 && <0.8,
-        http-types >=0.8 && <10.0,
+        http-types >=0.8 && <10,
         monad-control >=1.0 && <1.1,
-        mtl >=2.0 && <3.0,
         req,
-        text >=0.2 && <2.1
+        text >=0.2 && <2.2
 
     if flag(dev)
-        ghc-options: -O0 -Wall -Werror
+        ghc-options:
+            -Wall -Werror -Wredundant-constraints -Wpartial-fields
+            -Wunused-packages
 
     else
-        ghc-options: -O2 -Wall
+        buildable: False
