diff --git a/snap-server.cabal b/snap-server.cabal
--- a/snap-server.cabal
+++ b/snap-server.cabal
@@ -1,5 +1,5 @@
 name:           snap-server
-version:        0.4.3
+version:        0.5.0
 synopsis:       A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 description:
   Snap is a simple and fast web development framework and server written in
@@ -108,6 +108,7 @@
     blaze-builder-enumerator >= 0.2.0 && <0.3,
     bytestring,
     bytestring-nums,
+    case-insensitive >= 0.2 && < 0.3,
     containers,
     directory-tree,
     enumerator >= 0.4.7 && <0.5,
@@ -117,11 +118,11 @@
     murmur-hash >= 0.1 && < 0.2,
     network >= 2.3 && <2.4,
     old-locale,
-    snap-core >= 0.4.3 && <0.5,
+    snap-core >= 0.5 && <0.6,
     template-haskell,
+    text >= 0.11 && <0.12,
     time,
     transformers,
-    utf8-string,
     unix-compat == 0.2.*,
     vector >= 0.7 && <0.8,
     vector-algorithms >= 0.4 && <0.5,
diff --git a/src/Snap/Http/Server.hs b/src/Snap/Http/Server.hs
--- a/src/Snap/Http/Server.hs
+++ b/src/Snap/Http/Server.hs
@@ -43,46 +43,72 @@
 
 
 ------------------------------------------------------------------------------
--- | Starts serving HTTP requests using the given handler. Uses only the basic
--- settings from the given config; error handling and compression are ignored.
--- This function never returns; to shut down the HTTP server, kill the
--- controlling thread.
+-- | Starts serving HTTP requests using the given handler. This function never
+-- returns; to shut down the HTTP server, kill the controlling thread.
+--
+-- This function is like 'httpServe' except it doesn't setup compression or the
+-- error handler; this allows it to be used from 'MonadSnap'.
 simpleHttpServe :: MonadSnap m => Config m a -> Snap () -> IO ()
-simpleHttpServe config handler = do
-    setUnicodeLocale $ fromJust $ getLocale conf
-    Int.httpServe tout
-                  (map listenToInt $ getListen conf)
-                  (fmap backendToInt $ getBackend conf)
-                  (fromJust $ getHostname  conf)
-                  (fromJust $ getAccessLog conf)
-                  (fromJust $ getErrorLog  conf)
-                  (runSnap handler)
+simpleHttpServe config handler = do 
+    conf <- completeConfig config
+    let output   = when (fromJust $ getVerbose conf) . hPutStrLn stderr
+    mapM_ (output . ("Listening on "++) . show) $ listeners conf
+
+    go conf `finally` output "\nShutting down..."
   where
-    tout = fromMaybe 60 $ getDefaultTimeout config
-    conf = completeConfig config
-    listenToInt (ListenHttp b p) = Int.HttpPort b p
-    listenToInt (ListenHttps b p c k) = Int.HttpsPort b p c k
-    backendToInt ConfigSimpleBackend = Int.EventLoopSimple
-    backendToInt ConfigLibEvBackend  = Int.EventLoopLibEv
+    go conf = do
+        let tout = fromMaybe 60 $ getDefaultTimeout conf
+        setUnicodeLocale $ fromJust $ getLocale conf
+        Int.httpServe tout
+                      (listeners conf)
+                      (fmap backendToInternal $ getBackend conf)
+                      (fromJust $ getHostname  conf)
+                      (fromJust $ getAccessLog conf)
+                      (fromJust $ getErrorLog  conf)
+                      (runSnap handler)
+{-# INLINE simpleHttpServe #-}
 
 
+listeners :: Config m a -> [Int.ListenPort]
+listeners conf = catMaybes [ httpListener, httpsListener ]
+  where
+    httpsListener = do
+        b    <- getSSLBind conf
+        p    <- getSSLPort conf
+        cert <- getSSLCert conf
+        key  <- getSSLKey conf
+        return $ Int.HttpsPort b p cert key
+
+    httpListener = do
+        p <- getPort conf
+        b <- getBind conf
+        return $ Int.HttpPort b p
+
+
 ------------------------------------------------------------------------------
 -- | Starts serving HTTP requests using the given handler, with settings from
 -- the 'Config' passed in. This function never returns; to shut down the HTTP
 -- server, kill the controlling thread.
-httpServe :: Config Snap () -> Snap () -> IO ()
+httpServe :: Config Snap a -> Snap () -> IO ()
 httpServe config handler = do
-    mapM_ (output . ("Listening on "++) . show) $ getListen conf
-    serve handler `finally` output "\nShutting down..."
-  where
-    conf     = completeConfig config
-    output   = when (fromJust $ getVerbose conf) . hPutStrLn stderr
-    serve    = simpleHttpServe config . compress . catch500
-    catch500 = flip catch $ fromJust $ getErrorHandler conf
-    compress = if fromJust $ getCompression conf then withCompression else id
+    conf <- completeConfig config
+    let serve = compress conf . catch500 conf $ handler
+    simpleHttpServe conf serve
+{-# INLINE httpServe #-}
 
 
 ------------------------------------------------------------------------------
+catch500 :: MonadSnap m => Config m a -> m () -> m ()
+catch500 conf = flip catch $ fromJust $ getErrorHandler conf
+{-# INLINE catch500 #-}
+
+
+------------------------------------------------------------------------------
+compress :: MonadSnap m => Config m a -> m () -> m ()
+compress conf = if fromJust $ getCompression conf then withCompression else id
+{-# INLINE compress #-}
+
+------------------------------------------------------------------------------
 -- | Starts serving HTTP using the given handler. The configuration is read
 -- from the options given on the command-line, as returned by
 -- 'commandLineConfig'. This function never returns; to shut down the HTTP
@@ -95,23 +121,29 @@
 -- | Given a string like \"en_US\", this sets the locale to \"en_US.UTF-8\".
 -- This doesn't work on Windows.
 setUnicodeLocale :: String -> IO ()
-setUnicodeLocale lang =
+setUnicodeLocale =
 #ifndef PORTABLE
-    mapM_ (\k -> setEnv k (lang ++ ".UTF-8") True)
-          [ "LANG"
-          , "LC_CTYPE"
-          , "LC_NUMERIC"
-          , "LC_TIME"
-          , "LC_COLLATE"
-          , "LC_MONETARY"
-          , "LC_MESSAGES"
-          , "LC_PAPER"
-          , "LC_NAME"
-          , "LC_ADDRESS"
-          , "LC_TELEPHONE"
-          , "LC_MEASUREMENT"
-          , "LC_IDENTIFICATION"
-          , "LC_ALL" ]
+    \lang -> mapM_ (\k -> setEnv k (lang ++ ".UTF-8") True)
+               [ "LANG"
+               , "LC_CTYPE"
+               , "LC_NUMERIC"
+               , "LC_TIME"
+               , "LC_COLLATE"
+               , "LC_MONETARY"
+               , "LC_MESSAGES"
+               , "LC_PAPER"
+               , "LC_NAME"
+               , "LC_ADDRESS"
+               , "LC_TELEPHONE"
+               , "LC_MEASUREMENT"
+               , "LC_IDENTIFICATION"
+               , "LC_ALL" ]
 #else
-    return ()
+    const $ return ()
 #endif
+
+
+------------------------------------------------------------------------------
+backendToInternal :: ConfigBackend -> Int.EventLoopType
+backendToInternal ConfigSimpleBackend = Int.EventLoopSimple
+backendToInternal ConfigLibEvBackend  = Int.EventLoopLibEv
diff --git a/src/Snap/Http/Server/Config.hs b/src/Snap/Http/Server/Config.hs
--- a/src/Snap/Http/Server/Config.hs
+++ b/src/Snap/Http/Server/Config.hs
@@ -3,55 +3,68 @@
 
 {-|
 
-This module exports the 'Config' datatype which represents partially-specified
-configurations of \"serve\" functions which run 'Snap' actions in 'IO'.
+This module exports the 'Config' datatype, which you can use to configure the
+Snap HTTP server.
 
 -}
 
 module Snap.Http.Server.Config
   ( Config
-  , ConfigListen(..)
   , ConfigBackend(..)
+
   , emptyConfig
   , defaultConfig
-  , completeConfig
   , commandLineConfig
+  , completeConfig
 
-  , getHostname
-  , getListen
   , getAccessLog
-  , getErrorLog
-  , getLocale
   , getBackend
+  , getBind
   , getCompression
-  , getVerbose
-  , getErrorHandler
   , getDefaultTimeout
+  , getErrorHandler
+  , getErrorLog
+  , getHostname
+  , getLocale
   , getOther
+  , getPort
+  , getSSLBind
+  , getSSLCert
+  , getSSLKey
+  , getSSLPort
+  , getVerbose
 
-  , setHostname
-  , addListen
-  , setListen
   , setAccessLog
-  , setErrorLog
-  , setLocale
   , setBackend
+  , setBind
   , setCompression
-  , setVerbose
-  , setErrorHandler
   , setDefaultTimeout
+  , setErrorHandler
+  , setErrorLog
+  , setHostname
+  , setLocale
   , setOther
+  , setPort
+  , setSSLBind
+  , setSSLCert
+  , setSSLKey
+  , setSSLPort
+  , setVerbose
   ) where
 
+
 import           Blaze.ByteString.Builder
 import           Control.Exception (SomeException)
 import           Control.Monad
-import qualified Data.ByteString.UTF8 as U
 import qualified Data.ByteString.Char8 as B
 import           Data.ByteString (ByteString)
 import           Data.Char
+import           Data.Function
 import           Data.List
+import           Data.Maybe
 import           Data.Monoid
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
 import           Prelude hiding (catch)
 import           Snap.Types
 import           Snap.Iteratee ((>==>), enumBuilder)
@@ -64,301 +77,306 @@
 import           System.Exit
 import           System.IO
 
-------------------------------------------------------------------------------
--- | A data type to store the bind address and port to listen on.
---
---  For SSL support, it also stores the path to the certificate in PEM format
---  and the path to the private key in PEM format
-data ConfigListen = ListenHttp  ByteString Int
-                  | ListenHttps ByteString Int FilePath FilePath
 
-
-instance Show ConfigListen where
-    show (ListenHttp b p) = "http://" ++ U.toString b ++ ":" ++ show p
-    show (ListenHttps b p c k) =
-        "https://" ++ U.toString b ++ ":" ++ show p ++
-        " (cert = " ++ show c ++ ", key = " ++ show k ++ ")"
-
-
 ------------------------------------------------------------------------------
--- | A data type to record which backend event loop should be used when
--- serving data.
+-- | This datatype allows you to override which backend (either simple or
+-- libev) to use. Most users will not want to set this, preferring to rely on
+-- the compile-type default.
+--
+-- Note that if you specify the libev backend and have not compiled in support
+-- for it, your server will fail at runtime.
 data ConfigBackend = ConfigSimpleBackend
                    | ConfigLibEvBackend
-    deriving (Eq,Show)
-
+  deriving (Show, Eq)
 
 ------------------------------------------------------------------------------
 -- | A record type which represents partial configurations (for 'httpServe')
 -- by wrapping all of its fields in a 'Maybe'. Values of this type are usually
 -- constructed via its 'Monoid' instance by doing something like:
 --
--- > addListen (ListenHttp "0.0.0.0" 9000) mempty
+-- > setPort 1234 mempty
 --
 -- Any fields which are unspecified in the 'Config' passed to 'httpServe' (and
 -- this is the norm) are filled in with default values from 'defaultConfig'.
-data MonadSnap m => Config m a = Config
+data Config m a = Config
     { hostname       :: Maybe ByteString
-      -- ^ The name of the server
-    , listen         :: [ConfigListen]
-      -- ^ The local interfaces to listen on
     , accessLog      :: Maybe (Maybe FilePath)
-      -- ^ The path to the access log
     , errorLog       :: Maybe (Maybe FilePath)
-      -- ^ The path to the error log
     , locale         :: Maybe String
-      -- ^ The locale to use
-    , backend        :: Maybe ConfigBackend
-      -- ^ The backend to use
+    , port           :: Maybe Int
+    , bind           :: Maybe ByteString
+    , sslport        :: Maybe Int
+    , sslbind        :: Maybe ByteString
+    , sslcert        :: Maybe FilePath
+    , sslkey         :: Maybe FilePath
     , compression    :: Maybe Bool
-      -- ^ Whether to use compression
     , verbose        :: Maybe Bool
-      -- ^ Whether to write server status updates to stderr
     , errorHandler   :: Maybe (SomeException -> m ())
-      -- ^ A MonadSnap action to handle 500 errors
     , defaultTimeout :: Maybe Int
     , other          :: Maybe a
-      -- ^ This is for any other state needed to initialize a custom server
+    , backend        :: Maybe ConfigBackend
     }
 
+instance Show (Config m a) where
+    show c = unlines [ "Config:"
+                     , "hostname: "       ++ _hostname
+                     , "accessLog: "      ++ _accessLog
+                     , "errorLog: "       ++ _errorLog
+                     , "locale: "         ++ _locale
+                     , "port: "           ++ _port
+                     , "bind: "           ++ _bind
+                     , "sslport: "        ++ _sslport
+                     , "sslbind: "        ++ _sslbind
+                     , "sslcert: "        ++ _sslcert
+                     , "sslkey: "         ++ _sslkey
+                     , "compression: "    ++ _compression
+                     , "verbose: "        ++ _verbose
+                     , "defaultTimeout: " ++ _defaultTimeout
+                     , "backend: "        ++ _backend
+                     ]
 
-------------------------------------------------------------------------------
-instance MonadSnap m => Show (Config m a) where
-    show c = "Config {" ++ concat (intersperse ", " $ filter (/="") $ map ($c)
-        [ showM "hostname" . hostname
-        , showL "listen" . listen
-        , showM "accessLog" . accessLog
-        , showM "errorLog" . errorLog
-        , showM "locale" . locale
-        , showM "backend" . backend
-        , showM "compression" . compression
-        , showM "verbose" . verbose
-        , showM "errorHandler" . fmap (const ()) . errorHandler
-        , showM "defaultTimeout" . fmap (const ()) . defaultTimeout
-        ]) ++ "}"
       where
-        showM s   = maybe "" ((++) (s ++ " = ") . show)
-        showL s l = s ++ " = " ++ show l
+        _hostname       = show $ hostname       c
+        _accessLog      = show $ accessLog      c
+        _errorLog       = show $ errorLog       c
+        _locale         = show $ locale         c
+        _port           = show $ port           c
+        _bind           = show $ bind           c
+        _sslport        = show $ sslport        c
+        _sslbind        = show $ sslbind        c
+        _sslcert        = show $ sslcert        c
+        _sslkey         = show $ sslkey         c
+        _compression    = show $ compression    c
+        _verbose        = show $ verbose        c
+        _defaultTimeout = show $ defaultTimeout c
+        _backend        = show $ backend        c
 
 
 ------------------------------------------------------------------------------
 -- | Returns a completely empty 'Config'. Equivalent to 'mempty' from
 -- 'Config''s 'Monoid' instance.
-emptyConfig :: MonadSnap m => Config m a
+emptyConfig :: Config m a
 emptyConfig = mempty
 
 
 ------------------------------------------------------------------------------
-instance MonadSnap m => Monoid (Config m a) where
+instance Monoid (Config m a) where
     mempty = Config
         { hostname       = Nothing
-        , listen         = []
         , accessLog      = Nothing
         , errorLog       = Nothing
         , locale         = Nothing
-        , backend        = Nothing
+        , port           = Nothing
+        , bind           = Nothing
+        , sslport        = Nothing
+        , sslbind        = Nothing
+        , sslcert        = Nothing
+        , sslkey         = Nothing
         , compression    = Nothing
         , verbose        = Nothing
         , errorHandler   = Nothing
         , defaultTimeout = Nothing
         , other          = Nothing
+        , backend        = Nothing
         }
 
     a `mappend` b = Config
-        { hostname       = (hostname       b) `mplus` (hostname       a)
-        , listen         = (listen         b)   ++    (listen         a)
-        , accessLog      = (accessLog      b) `mplus` (accessLog      a)
-        , errorLog       = (errorLog       b) `mplus` (errorLog       a)
-        , locale         = (locale         b) `mplus` (locale         a)
-        , backend        = (backend        b) `mplus` (backend        a)
-        , compression    = (compression    b) `mplus` (compression    a)
-        , verbose        = (verbose        b) `mplus` (verbose        a)
-        , errorHandler   = (errorHandler   b) `mplus` (errorHandler   a)
-        , defaultTimeout = (defaultTimeout b) `mplus` (defaultTimeout a)
-        , other          = (other          b) `mplus` (other          a)
+        { hostname       = ov hostname       a b
+        , accessLog      = ov accessLog      a b
+        , errorLog       = ov errorLog       a b
+        , locale         = ov locale         a b
+        , port           = ov port           a b
+        , bind           = ov bind           a b
+        , sslport        = ov sslport        a b
+        , sslbind        = ov sslbind        a b
+        , sslcert        = ov sslcert        a b
+        , sslkey         = ov sslkey         a b
+        , compression    = ov compression    a b
+        , verbose        = ov verbose        a b
+        , errorHandler   = ov errorHandler   a b
+        , defaultTimeout = ov defaultTimeout a b
+        , other          = ov other          a b
+        , backend        = ov backend        a b
         }
+      where
+        ov f x y = getLast $! (mappend `on` (Last . f)) x y
 
 
 ------------------------------------------------------------------------------
--- | These are the default values for all the fields in 'Config'.
---
--- > hostname     = "localhost"
--- > listen       = []
--- > accessLog    = "log/access.log"
--- > errorLog     = "log/error.log"
--- > locale       = "en_US"
--- > backend      = Nothing (the backend is selected based on compile options)
--- > compression  = True
--- > verbose      = True
--- > errorHandler = prints the error message
---
+-- | These are the default values for the options
 defaultConfig :: MonadSnap m => Config m a
-defaultConfig = Config
+defaultConfig = mempty
     { hostname       = Just "localhost"
-    , listen         = []
     , accessLog      = Just $ Just "log/access.log"
     , errorLog       = Just $ Just "log/error.log"
     , locale         = Just "en_US"
-    , backend        = Nothing
     , compression    = Just True
     , verbose        = Just True
     , errorHandler   = Just defaultErrorHandler
+    , bind           = Just "0.0.0.0"
+    , sslbind        = Just "0.0.0.0"
+    , sslcert        = Just "cert.pem"
+    , sslkey         = Just "key.pem"
     , defaultTimeout = Just 60
-    , other          = Nothing
     }
 
 
 ------------------------------------------------------------------------------
-defaultErrorHandler :: MonadSnap m => SomeException -> m ()
-defaultErrorHandler e = do
-    debug "Snap.Http.Server.Config errorHandler: got exception:"
-    debug $ show e
-    logError msg
-    finishWith $ setContentType "text/plain; charset=utf-8"
-               . setContentLength (fromIntegral $ B.length msg)
-               . setResponseStatus 500 "Internal Server Error"
-               . modifyResponseBody
-                     (>==> enumBuilder (fromByteString msg))
-               $ emptyResponse
-  where    
-    err = U.fromString $ show e
-    msg = mappend "A web handler threw an exception. Details:\n" err
+-- | The hostname of the HTTP server
+getHostname       :: Config m a -> Maybe ByteString
+getHostname = hostname
 
-------------------------------------------------------------------------------
--- | Completes a partial 'Config' by filling in the unspecified values with
--- the default values from 'defaultConfig'.  Also, if no listeners are
--- specified, adds a http listener on 0.0.0.0:8000
-completeConfig :: MonadSnap m => Config m a -> Config m a
-completeConfig c = case listen c' of
-                    [] -> addListen (ListenHttp "0.0.0.0" 8000) c'
-                    _  -> c'
-    where c' = mappend defaultConfig c
+-- | Path to the access log
+getAccessLog      :: Config m a -> Maybe (Maybe FilePath)
+getAccessLog = accessLog
 
+-- | Path to the error log
+getErrorLog       :: Config m a -> Maybe (Maybe FilePath)
+getErrorLog = errorLog
 
-------------------------------------------------------------------------------
--- | A data structure used during command-line option parsing
---
--- The Config data type allows a list of listen ports, but the command line
--- options only allow one http and one https listener.  This data structure
--- is used during option parsing
-data MonadSnap m => OptionData m a = OptionData
-    { config  :: Config m a
-    , bind    :: Maybe ByteString
-    , port    :: Maybe Int
-    , sslbind :: Maybe ByteString
-    , sslport :: Maybe Int
-    , sslcert :: Maybe FilePath
-    , sslkey  :: Maybe FilePath
-    , tout    :: Maybe Int
-    }
+-- | The locale to use
+getLocale         :: Config m a -> Maybe String
+getLocale = locale
 
+-- | Returns the port to listen on (for http)
+getPort           :: Config m a -> Maybe Int
+getPort = port
 
-------------------------------------------------------------------------------
-instance MonadSnap m => Monoid (OptionData m a) where
-    mempty = OptionData
-        { config  = mempty
-        , bind    = Nothing
-        , port    = Nothing
-        , sslbind = Nothing
-        , sslport = Nothing
-        , sslcert = Nothing
-        , sslkey  = Nothing
-        , tout    = Nothing
-        }
+-- | Returns the address to bind to (for http)
+getBind           :: Config m a -> Maybe ByteString
+getBind = bind
 
-    a `mappend` b = OptionData
-        { config       = (config       b) `mappend` (config       a)
-        , bind         = (bind         b) `mplus`   (bind         a)
-        , port         = (port         b) `mplus`   (port         a)
-        , sslbind      = (sslbind      b) `mplus`   (sslbind      a)
-        , sslport      = (sslport      b) `mplus`   (sslport      a)
-        , sslcert      = (sslcert      b) `mplus`   (sslcert      a)
-        , sslkey       = (sslkey       b) `mplus`   (sslkey       a)
-        , tout         = (tout         b) `mplus`   (tout         a)
-        }
+-- | Returns the port to listen on (for https)
+getSSLPort        :: Config m a -> Maybe Int
+getSSLPort = sslport
 
+-- | Returns the address to bind to (for https)
+getSSLBind        :: Config m a -> Maybe ByteString
+getSSLBind = sslbind
 
+-- | Path to the SSL certificate file
+getSSLCert        :: Config m a -> Maybe FilePath
+getSSLCert = sslcert
+
+-- | Path to the SSL key file
+getSSLKey         :: Config m a -> Maybe FilePath
+getSSLKey = sslkey
+
+-- | If set and set to True, compression is turned on when applicable
+getCompression    :: Config m a -> Maybe Bool
+getCompression = compression
+
+-- | Whether to write server status updates to stderr
+getVerbose        :: Config m a -> Maybe Bool
+getVerbose = verbose
+
+-- | A MonadSnap action to handle 500 errors
+getErrorHandler   :: Config m a -> Maybe (SomeException -> m ())
+getErrorHandler = errorHandler
+
+getDefaultTimeout :: Config m a -> Maybe Int
+getDefaultTimeout = defaultTimeout
+
+getOther :: Config m a -> Maybe a
+getOther = other
+
+getBackend :: Config m a -> Maybe ConfigBackend
+getBackend = backend
+
+
 ------------------------------------------------------------------------------
--- | These are the default values for the options
-defaultOptions :: MonadSnap m => OptionData m a
-defaultOptions = OptionData
-    { config  = defaultConfig
-    , bind    = Just "0.0.0.0"
-    , port    = Just 8000
-    , sslbind = Just "0.0.0.0"
-    , sslport = Nothing
-    , sslcert = Just "cert.pem"
-    , sslkey  = Just "key.pem"
-    , tout    = Just 60
-    }
+setHostname       :: ByteString              -> Config m a -> Config m a
+setHostname x c = c { hostname = Just x }
 
+setAccessLog      :: (Maybe FilePath)        -> Config m a -> Config m a
+setAccessLog x c = c { accessLog = Just x }
 
+setErrorLog       :: (Maybe FilePath)        -> Config m a -> Config m a
+setErrorLog x c = c { errorLog = Just x }
+
+setLocale         :: String                  -> Config m a -> Config m a
+setLocale x c = c { locale = Just x }
+
+setPort           :: Int                     -> Config m a -> Config m a
+setPort x c = c { port = Just x }
+
+setBind           :: ByteString              -> Config m a -> Config m a
+setBind x c = c { bind = Just x }
+
+setSSLPort        :: Int                     -> Config m a -> Config m a
+setSSLPort x c = c { sslport = Just x }
+
+setSSLBind        :: ByteString              -> Config m a -> Config m a
+setSSLBind x c = c { sslbind = Just x }
+
+setSSLCert        :: FilePath                -> Config m a -> Config m a
+setSSLCert x c = c { sslcert = Just x }
+
+setSSLKey         :: FilePath                -> Config m a -> Config m a
+setSSLKey x c = c { sslkey = Just x }
+
+setCompression    :: Bool                    -> Config m a -> Config m a
+setCompression x c = c { compression = Just x }
+
+setVerbose        :: Bool                    -> Config m a -> Config m a
+setVerbose x c = c { verbose = Just x }
+
+setErrorHandler   :: (SomeException -> m ()) -> Config m a -> Config m a
+setErrorHandler x c = c { errorHandler = Just x }
+
+setDefaultTimeout :: Int                     -> Config m a -> Config m a
+setDefaultTimeout x c = c { defaultTimeout = Just x }
+
+setOther          :: a                       -> Config m a -> Config m a
+setOther x c = c { other = Just x }
+
+setBackend        :: ConfigBackend           -> Config m a -> Config m a
+setBackend x c = c { backend = Just x }
+
+
 ------------------------------------------------------------------------------
--- | Convert options to config
-optionsToConfig :: MonadSnap m => OptionData m a -> Config m a
-optionsToConfig o = mconcat $ [config o] ++ http ++ https ++ [tmOut]
-    where lhttp  = maybe2 [] ListenHttp  (bind o) (port o)
-          lhttps = maybe4 [] ListenHttps (sslbind o)
-                                         (sslport o)
-                                         (sslcert o)
-                                         (sslkey  o)
-          http  = map (flip addListen mempty) lhttp
-          https = map (flip addListen mempty) lhttps
+completeConfig :: (MonadSnap m) => Config m a -> IO (Config m a)
+completeConfig config = do
+    when noPort $ hPutStrLn stderr "no port specified, defaulting to port 8000"
 
-          maybe2 _ f (Just a) (Just b) = [f a b]
-          maybe2 d _ _        _        = d
-          maybe4 _ f (Just a) (Just b) (Just c) (Just d) = [f a b c d]
-          maybe4 d _ _        _        _        _        = d
+    return $ cfg `mappend` cfg'
 
-          tmOut = maybe mempty
-                        (\t -> mempty { defaultTimeout = Just t })
-                        (tout o)
+  where
+    cfg = defaultConfig `mappend` config
 
+    sslVals = map ($ cfg) [ isJust . getSSLPort
+                          , isJust . getSSLBind
+                          , isJust . getSSLKey
+                          , isJust . getSSLCert ]
+
+    sslValid   = and sslVals
+    noPort = isNothing (getPort cfg) && not sslValid
+
+    cfg' = emptyConfig { port = if noPort then Just 8000 else Nothing }
+
+
 ------------------------------------------------------------------------------
--- | Convert config to options
-configToOptions :: MonadSnap m => Config m a -> OptionData m a
-configToOptions c = OptionData
-    { config  = c
-    , bind    = Nothing
-    , port    = Nothing
-    , sslbind = Nothing
-    , sslport = Nothing
-    , sslcert = Nothing
-    , sslkey  = Nothing
-    , tout    = (defaultTimeout c)
-    }
+fromString :: String -> ByteString
+fromString = T.encodeUtf8 . T.pack
 
 
 ------------------------------------------------------------------------------
--- | A description of the command-line options accepted by
--- 'commandLineConfig'.
---
--- The 'OptionData' parameter is just for specifying any default values which
--- are to override those in 'defaultOptions'. This is so the usage message can
--- accurately inform the user what the default values for the options are. In
--- most cases, you will probably just end up passing 'mempty' for this
--- parameter.
---
--- The return type is a list of options describing @'Maybe' ('OptionData' m)@
--- as opposed to @'OptionData' m@, because if the @--help@ option is given,
--- the set of command-line options no longer describe a config, but an action
--- (printing out the usage message).
-options :: MonadSnap m
-        => OptionData m a
-        -> [OptDescr (Maybe (OptionData m a))]
+options :: MonadSnap m =>
+           Config m a
+        -> [OptDescr (Maybe (Config m a))]
 options defaults =
     [ Option [] ["hostname"]
-             (ReqArg (Just . setConfig setHostname . U.fromString) "NAME")
+             (ReqArg (Just . setConfig setHostname . fromString) "NAME")
              $ "local hostname" ++ defaultC getHostname
     , Option ['b'] ["address"]
-             (ReqArg (\s -> Just $ mempty { bind = Just $ U.fromString s })
+             (ReqArg (\s -> Just $ mempty { bind = Just $ fromString s })
                      "ADDRESS")
              $ "address to bind to" ++ defaultO bind
     , Option ['p'] ["port"]
              (ReqArg (\s -> Just $ mempty { port = Just $ read s}) "PORT")
              $ "port to listen on" ++ defaultO port
     , Option [] ["ssl-address"]
-             (ReqArg (\s -> Just $ mempty { sslbind = Just $ U.fromString s })
+             (ReqArg (\s -> Just $ mempty { sslbind = Just $ fromString s })
                      "ADDRESS")
              $ "ssl address to bind to" ++ defaultO sslbind
     , Option [] ["ssl-port"]
@@ -386,7 +404,9 @@
              (NoArg $ Just $ setConfig setCompression True)
              $ "use gzip compression on responses"
     , Option ['t'] ["timeout"]
-             (ReqArg (\t -> Just $ mempty { tout = Just $ read t}) "SECS")
+             (ReqArg (\t -> Just $ mempty {
+                              defaultTimeout = Just $ read t
+                            }) "SECS")
              $ "set default timeout in seconds"
     , Option [] ["no-compression"]
              (NoArg $ Just $ setConfig setCompression False)
@@ -402,162 +422,72 @@
              $ "display this help and exit"
     ]
   where
-    setConfig f c = configToOptions $ f c mempty
-    conf          = completeConfig $ config defaults
-    opts          = mappend defaultOptions defaults
+    setConfig f c = f c mempty
+    conf          = defaultConfig `mappend` defaults
     defaultC f    = maybe "" ((", default " ++) . show) $ f conf
-    defaultO f    = maybe ", default off" ((", default " ++) . show) $ f opts
+    defaultO f    = maybe ", default off" ((", default " ++) . show) $ f conf
 
 
+
+
 ------------------------------------------------------------------------------
--- | This returns a 'Config' gotten from parsing the options specified on the
+defaultErrorHandler :: MonadSnap m => SomeException -> m ()
+defaultErrorHandler e = do
+    debug "Snap.Http.Server.Config errorHandler: got exception:"
+    debug $ show e
+    logError msg
+    finishWith $ setContentType "text/plain; charset=utf-8"
+               . setContentLength (fromIntegral $ B.length msg)
+               . setResponseStatus 500 "Internal Server Error"
+               . modifyResponseBody
+                     (>==> enumBuilder (fromByteString msg))
+               $ emptyResponse
+  where
+    err = fromString $ show e
+    msg = mappend "A web handler threw an exception. Details:\n" err
+
+
+
+------------------------------------------------------------------------------
+-- | Returns a 'Config' obtained from parsing the options specified on the
 -- command-line.
 --
--- The 'Config' parameter is just for specifying any default values which are
--- to override those in 'defaultConfig'. This is so the usage message can
--- accurately inform the user what the default values for the options are. In
--- most cases, you will probably just end up passing 'mempty' for this
--- parameter.
---
 -- On Unix systems, the locale is read from the @LANG@ environment variable.
-commandLineConfig :: MonadSnap m => Config m a -> IO (Config m a)
+commandLineConfig :: MonadSnap m =>
+                     Config m a   -- ^ default configuration. This is combined
+                                  -- with 'defaultConfig' to obtain default
+                                  -- values to use if the given parameter is not
+                                  -- specified on the command line. Usually it is
+                                  -- fine to use 'emptyConfig' here.
+                  -> IO (Config m a)
 commandLineConfig defaults = do
     args <- getArgs
     prog <- getProgName
 
-    result <- either (usage prog) return $ case getOpt Permute opts args of
-        (f, _, []  ) -> maybe (Left []) Right $ fmap mconcat $ sequence f
-        (_, _, errs) -> Left errs
+    let opts = options defaults
 
-    let result' = optionsToConfig $ mappend defaultOptions result
+    result <- either (usage prog opts)
+                     return
+                     (case getOpt Permute opts args of
+                        (f, _, []  ) -> maybe (Left []) Right $
+                                        fmap mconcat $ sequence f
+                        (_, _, errs) -> Left errs)
 
 #ifndef PORTABLE
     lang <- getEnv "LANG"
-    return $ mconcat [defaults, result', mempty {locale = fmap upToUtf8 lang}]
+    completeConfig $ mconcat [defaults,
+                              mempty {locale = fmap upToUtf8 lang},
+                              result]
 #else
-    return $ mconcat [defaults, result']
+    completeConfig $ mconcat [defaults, result]
 #endif
 
   where
-    opts = options $ configToOptions defaults
-    usage prog errs = do
+    usage prog opts errs = do
         let hdr = "Usage:\n  " ++ prog ++ " [OPTION...]\n\nOptions:"
         let msg = concat errs ++ usageInfo hdr opts
         hPutStrLn stderr msg
         exitFailure
+#ifndef PORTABLE
     upToUtf8 = takeWhile $ \c -> isAlpha c || '_' == c
-
-
-------------------------------------------------------------------------------
-getHostname :: MonadSnap m => Config m a -> Maybe ByteString
-getHostname = hostname
-
-
-------------------------------------------------------------------------------
-getListen :: MonadSnap m => Config m a -> [ConfigListen]
-getListen = listen
-
-
-------------------------------------------------------------------------------
-getAccessLog :: MonadSnap m => Config m a -> Maybe (Maybe FilePath)
-getAccessLog = accessLog
-
-
-------------------------------------------------------------------------------
-getErrorLog :: MonadSnap m => Config m a -> Maybe (Maybe FilePath)
-getErrorLog = errorLog
-
-
-------------------------------------------------------------------------------
-getLocale :: MonadSnap m => Config m a -> Maybe String
-getLocale = locale
-
-
-------------------------------------------------------------------------------
-getBackend :: MonadSnap m => Config m a -> Maybe ConfigBackend
-getBackend = backend
-
-------------------------------------------------------------------------------
-getCompression :: MonadSnap m => Config m a -> Maybe Bool
-getCompression = compression
-
-
-------------------------------------------------------------------------------
-getVerbose :: MonadSnap m => Config m a -> Maybe Bool
-getVerbose = verbose
-
-
-------------------------------------------------------------------------------
-getErrorHandler :: MonadSnap m => Config m a -> Maybe (SomeException -> m ())
-getErrorHandler = errorHandler
-
-
-------------------------------------------------------------------------------
-getOther :: MonadSnap m => Config m a -> Maybe a
-getOther = other
-
-
-------------------------------------------------------------------------------
-getDefaultTimeout :: MonadSnap m => Config m a -> Maybe Int
-getDefaultTimeout = defaultTimeout
-
-
-------------------------------------------------------------------------------
-setHostname :: MonadSnap m => ByteString -> Config m a -> Config m a
-setHostname a m = m {hostname = Just a}
-
-
-------------------------------------------------------------------------------
-addListen :: MonadSnap m => ConfigListen -> Config m a -> Config m a
-addListen a m = m {listen = a : listen m}
-
-
-------------------------------------------------------------------------------
-setListen :: MonadSnap m => [ConfigListen] -> Config m a -> Config m a
-setListen a m = m {listen = a}
-
-
-------------------------------------------------------------------------------
-setAccessLog :: MonadSnap m => Maybe FilePath -> Config m a -> Config m a
-setAccessLog a m = m {accessLog = Just a}
-
-
-------------------------------------------------------------------------------
-setErrorLog :: MonadSnap m => Maybe FilePath -> Config m a -> Config m a
-setErrorLog a m = m {errorLog = Just a}
-
-
-------------------------------------------------------------------------------
-setLocale :: MonadSnap m => String -> Config m a -> Config m a
-setLocale a m = m {locale = Just a}
-
-
-------------------------------------------------------------------------------
-setBackend :: MonadSnap m => ConfigBackend -> Config m a -> Config m a
-setBackend a m = m { backend = Just a}
-
-
-------------------------------------------------------------------------------
-setCompression :: MonadSnap m => Bool -> Config m a -> Config m a
-setCompression a m = m {compression = Just a}
-
-
-------------------------------------------------------------------------------
-setVerbose :: MonadSnap m => Bool -> Config m a -> Config m a
-setVerbose a m = m {verbose = Just a}
-
-
-------------------------------------------------------------------------------
-setErrorHandler :: MonadSnap m => (SomeException -> m ()) -> Config m a
-                -> Config m a
-setErrorHandler a m = m {errorHandler = Just a}
-
-
-------------------------------------------------------------------------------
-setOther :: MonadSnap m => a -> Config m a -> Config m a
-setOther a m = m {other = Just a}
-
-
-------------------------------------------------------------------------------
-setDefaultTimeout :: MonadSnap m => Int -> Config m a -> Config m a
-setDefaultTimeout t m = m {defaultTimeout = Just t}
+#endif
diff --git a/src/Snap/Internal/Http/Server.hs b/src/Snap/Internal/Http/Server.hs
--- a/src/Snap/Internal/Http/Server.hs
+++ b/src/Snap/Internal/Http/Server.hs
@@ -16,7 +16,8 @@
 import           Control.Monad.State.Strict
 import           Control.Exception
 import           Data.Char
-import           Data.CIByteString
+import           Data.CaseInsensitive   (CI)
+import qualified Data.CaseInsensitive as CI
 import           Data.ByteString (ByteString)
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Char8 as SC
@@ -82,7 +83,14 @@
     -- (bind address, port, path to certificate, path to key)
     HttpsPort ByteString Int FilePath FilePath
 
+------------------------------------------------------------------------------
+instance Show ListenPort where
+    show (HttpPort b p) =
+        concat [ "http://", SC.unpack b, ":", show p, "/" ]
+    show (HttpsPort b p _ _) =
+        concat [ "https://", SC.unpack b, ":", show p, "/" ]
 
+
 ------------------------------------------------------------------------------
 data EventLoopType = EventLoopSimple
                    | EventLoopLibEv
@@ -484,7 +492,7 @@
 
       where
         isChunked = maybe False
-                          ((== ["chunked"]) . map toCI)
+                          ((== ["chunked"]) . map CI.mk)
                           (Map.lookup "transfer-encoding" hdrs)
 
         hasContentLength :: Int64 -> ServerMonad ()
@@ -720,7 +728,7 @@
 
 
     --------------------------------------------------------------------------
-    buildHdrs :: Map CIByteString [ByteString]
+    buildHdrs :: Map (CI ByteString) [ByteString]
               -> (Builder,Int)
     buildHdrs hdrs =
         {-# SCC "buildHdrs" #-}
@@ -740,7 +748,7 @@
 
         h k ys = foldl' (doOne kb klen) (mempty,0) ys
           where
-            k'      = unCI k
+            k'      = CI.original k
             kb      = fromByteString k' `mappend` fromByteString ": "
             klen    = S.length k' + 2
 
@@ -903,7 +911,7 @@
 toHeaders :: [(ByteString,ByteString)] -> Headers
 toHeaders kvps = foldl' f Map.empty kvps'
   where
-    kvps'     = map (first toCI . second (:[])) kvps
+    kvps'     = map (first CI.mk . second (:[])) kvps
     f m (k,v) = Map.insertWith' (flip (++)) k v m
 
 
diff --git a/src/Snap/Internal/Http/Server/Backend.hs b/src/Snap/Internal/Http/Server/Backend.hs
--- a/src/Snap/Internal/Http/Server/Backend.hs
+++ b/src/Snap/Internal/Http/Server/Backend.hs
@@ -88,6 +88,7 @@
     show (ListenHttp s) = "ListenHttp (" ++ show s ++ ")"
     show (ListenHttps s _ _) = "ListenHttps (" ++ show s ++ ")"
 
+
 ------------------------------------------------------------------------------
 data NetworkSession = NetworkSession
   { _socket     :: CInt
diff --git a/test/pongserver/Main.hs b/test/pongserver/Main.hs
--- a/test/pongserver/Main.hs
+++ b/test/pongserver/Main.hs
@@ -28,7 +28,7 @@
 
   where
     go m   = httpServe config pongServer `finally` putMVar m ()
-    config = addListen (ListenHttp "*" 8000) $
+    config = setPort 8000 $
              setErrorLog Nothing $
              setAccessLog Nothing $
              setCompression False $ emptyConfig
diff --git a/test/runTestsAndCoverage.sh b/test/runTestsAndCoverage.sh
--- a/test/runTestsAndCoverage.sh
+++ b/test/runTestsAndCoverage.sh
@@ -28,7 +28,6 @@
 mkdir -p $DIR
 
 EXCLUDES='Main
-Data.CIByteString
 Data.Concurrent.HashMap.Internal
 Data.Concurrent.HashMap.Tests
 Paths_snap_server
diff --git a/test/snap-server-testsuite.cabal b/test/snap-server-testsuite.cabal
--- a/test/snap-server-testsuite.cabal
+++ b/test/snap-server-testsuite.cabal
@@ -17,218 +17,219 @@
   Default: False
 
 Executable testsuite
-   hs-source-dirs:  suite common ../src
-   main-is:         TestSuite.hs
+  hs-source-dirs:  suite common ../src
+  main-is:         TestSuite.hs
 
-   build-depends:
-     QuickCheck >= 2,
-     array >= 0.3 && <0.4,
-     attoparsec >= 0.8.1 && < 0.9,
-     attoparsec-enumerator >= 0.2.0.1 && < 0.3,
-     base >= 4 && < 5,
-     base16-bytestring == 0.1.*,
-     binary >= 0.5 && < 0.6,
-     blaze-builder >= 0.2.1.4 && <0.4,
-     blaze-builder-enumerator >= 0.2.0 && <0.3,
-     bytestring,
-     bytestring-nums >= 0.3.1 && < 0.4,
-     containers,
-     directory,
-     directory-tree,
-     enumerator >= 0.4.7 && <0.5,
-     filepath,
-     haskell98,
-     http-enumerator >= 0.3.1 && <0.4,
-     HUnit >= 1.2 && < 2,
-     monads-fd >= 0.1.0.4 && <0.2,
-     murmur-hash >= 0.1 && < 0.2,
-     network == 2.3.*,
-     old-locale,
-     parallel > 2,
-     process,
-     snap-core >= 0.4.3 && <0.5,
-     template-haskell,
-     test-framework >= 0.3.1 && <0.4,
-     test-framework-hunit >= 0.2.5 && < 0.3,
-     test-framework-quickcheck2 >= 0.2.6 && < 0.3,
-     time,
-     transformers,
-     utf8-string >= 0.3.6 && <0.4,
-     vector >= 0.7 && <0.8,
-     vector-algorithms >= 0.4 && <0.5,
-     PSQueue >= 1.1 && <1.2
+  build-depends:
+    QuickCheck >= 2,
+    array >= 0.3 && <0.4,
+    attoparsec >= 0.8.1 && < 0.9,
+    attoparsec-enumerator >= 0.2.0.1 && < 0.3,
+    base >= 4 && < 5,
+    base16-bytestring == 0.1.*,
+    binary >= 0.5 && < 0.6,
+    blaze-builder >= 0.2.1.4 && <0.4,
+    blaze-builder-enumerator >= 0.2.0 && <0.3,
+    bytestring,
+    bytestring-nums >= 0.3.1 && < 0.4,
+    containers,
+    directory,
+    directory-tree,
+    enumerator >= 0.4.7 && <0.5,
+    filepath,
+    haskell98,
+    http-enumerator >= 0.6.5.3 && <0.7,
+    HUnit >= 1.2 && < 2,
+    monads-fd >= 0.1.0.4 && <0.2,
+    murmur-hash >= 0.1 && < 0.2,
+    network == 2.3.*,
+    old-locale,
+    parallel > 2,
+    process,
+    snap-core >= 0.5 && <0.6,
+    template-haskell,
+    test-framework >= 0.3.1 && <0.4,
+    test-framework-hunit >= 0.2.5 && < 0.3,
+    test-framework-quickcheck2 >= 0.2.6 && < 0.3,
+    text >= 0.11 && <0.12,
+    time,
+    transformers,
+    vector >= 0.7 && <0.8,
+    vector-algorithms >= 0.4 && <0.5,
+    PSQueue >= 1.1 && <1.2
 
-   if !os(windows)
-     build-depends: unix
+  if !os(windows)
+    build-depends: unix
 
-   if flag(libev)
-     build-depends: hlibev >= 0.2.5 && < 0.3
-     cpp-options: -DLIBEV
+  if flag(libev)
+    build-depends: hlibev >= 0.2.5 && < 0.3
+    cpp-options: -DLIBEV
 
-   if flag(gnutls)
-     extra-libraries: gnutls
-     cpp-options: -DGNUTLS
-     c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
+  if flag(gnutls)
+    extra-libraries: gnutls
+    cpp-options: -DGNUTLS
+    c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
 
-   if flag(portable) || os(windows)
-     cpp-options: -DPORTABLE
+  if flag(portable) || os(windows)
+    cpp-options: -DPORTABLE
 
-   ghc-prof-options: -prof -auto-all
-   ghc-options: -O2 -Wall -fhpc -fwarn-tabs
-                -funbox-strict-fields -threaded
-                -fno-warn-unused-do-bind
+  ghc-prof-options: -prof -auto-all
+  ghc-options: -O2 -Wall -fhpc -fwarn-tabs
+               -funbox-strict-fields -threaded
+               -fno-warn-unused-do-bind
 
 
 Executable pongserver
-   hs-source-dirs:  pongserver common ../src
-   main-is:         Main.hs
+  hs-source-dirs:  pongserver common ../src
+  main-is:         Main.hs
 
-   build-depends:
-     QuickCheck >= 2,
-     array >= 0.3 && <0.4,
-     attoparsec >= 0.8.1 && < 0.9,
-     attoparsec-enumerator >= 0.2.0.1 && < 0.3,
-     base >= 4 && < 5,
-     base16-bytestring == 0.1.*,
-     blaze-builder >= 0.2.1.4 && <0.4,
-     blaze-builder-enumerator >= 0.2.0 && <0.3,
-     bytestring,
-     bytestring-nums >= 0.3.1 && < 0.4,
-     cereal >= 0.3 && < 0.4,
-     containers,
-     directory-tree,
-     enumerator >= 0.4.7 && <0.5,
-     filepath,
-     haskell98,
-     HUnit >= 1.2 && < 2,
-     monads-fd >= 0.1.0.4 && <0.2,
-     murmur-hash >= 0.1 && < 0.2,
-     old-locale,
-     parallel > 2,
-     MonadCatchIO-transformers >= 0.2.1 && < 0.3,
-     network == 2.3.*,
-     snap-core >= 0.4.1 && <0.5,
-     template-haskell,
-     time,
-     transformers,
-     unix-compat == 0.2.*,
-     utf8-string >= 0.3.6 && <0.4,
-     vector >= 0.7 && <0.8,
-     vector-algorithms >= 0.4 && <0.5,
-     PSQueue >= 1.1 && <1.2
+  build-depends:
+    QuickCheck >= 2,
+    array >= 0.3 && <0.4,
+    attoparsec >= 0.8.1 && < 0.9,
+    attoparsec-enumerator >= 0.2.0.1 && < 0.3,
+    base >= 4 && < 5,
+    base16-bytestring == 0.1.*,
+    blaze-builder >= 0.2.1.4 && <0.4,
+    blaze-builder-enumerator >= 0.2.0 && <0.3,
+    bytestring,
+    bytestring-nums >= 0.3.1 && < 0.4,
+    cereal >= 0.3 && < 0.4,
+    containers,
+    directory-tree,
+    enumerator >= 0.4.7 && <0.5,
+    filepath,
+    haskell98,
+    HUnit >= 1.2 && < 2,
+    monads-fd >= 0.1.0.4 && <0.2,
+    murmur-hash >= 0.1 && < 0.2,
+    old-locale,
+    parallel > 2,
+    MonadCatchIO-transformers >= 0.2.1 && < 0.3,
+    network == 2.3.*,
+    snap-core >= 0.5 && <0.6,
+    template-haskell,
+    time,
+    transformers,
+    unix-compat == 0.2.*,
+    utf8-string >= 0.3.6 && <0.4,
+    vector >= 0.7 && <0.8,
+    vector-algorithms >= 0.4 && <0.5,
+    PSQueue >= 1.1 && <1.2
 
-   if flag(portable) || os(windows)
-     cpp-options: -DPORTABLE
-   else
-     build-depends: unix
+  if flag(portable) || os(windows)
+    cpp-options: -DPORTABLE
+  else
+    build-depends: unix
 
-   if flag(libev)
-     build-depends: hlibev >= 0.2.5 && < 0.3
-     cpp-options: -DLIBEV
+  if flag(libev)
+    build-depends: hlibev >= 0.2.5 && < 0.3
+    cpp-options: -DLIBEV
 
-   if flag(gnutls)
-     extra-libraries: gnutls
-     cpp-options: -DGNUTLS
-     c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
+  if flag(gnutls)
+    extra-libraries: gnutls
+    cpp-options: -DGNUTLS
+    c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
 
-   if os(linux) && !flag(portable)
-     cpp-options: -DLINUX -DHAS_SENDFILE
-     other-modules:
-       System.SendFile,
-       System.SendFile.Linux
+  if os(linux) && !flag(portable)
+    cpp-options: -DLINUX -DHAS_SENDFILE
+    other-modules:
+      System.SendFile,
+      System.SendFile.Linux
 
-   if os(darwin) && !flag(portable)
-     cpp-options: -DOSX -DHAS_SENDFILE
-     other-modules:
-       System.SendFile,
-       System.SendFile.Darwin
+  if os(darwin) && !flag(portable)
+    cpp-options: -DOSX -DHAS_SENDFILE
+    other-modules:
+      System.SendFile,
+      System.SendFile.Darwin
 
-   if os(freebsd) && !flag(portable)
-     cpp-options: -DFREEBSD -DHAS_SENDFILE
-     other-modules:
-       System.SendFile,
-       System.SendFile.FreeBSD
+  if os(freebsd) && !flag(portable)
+    cpp-options: -DFREEBSD -DHAS_SENDFILE
+    other-modules:
+      System.SendFile,
+      System.SendFile.FreeBSD
 
-   if flag(portable) || os(windows)
-     cpp-options: -DPORTABLE
+  if flag(portable) || os(windows)
+    cpp-options: -DPORTABLE
 
-   ghc-options: -Wall -O2 -fwarn-tabs -funbox-strict-fields -threaded
-                -fno-warn-unused-do-bind
-   ghc-prof-options: -prof -auto-all
+  ghc-options: -Wall -O2 -fwarn-tabs -funbox-strict-fields -threaded
+               -fno-warn-unused-do-bind
+  ghc-prof-options: -prof -auto-all
 
 
 Executable testserver
-   hs-source-dirs:  testserver common ../src
-   main-is:         Main.hs
+  hs-source-dirs:  testserver common ../src
+  main-is:         Main.hs
 
-   build-depends:
-     QuickCheck >= 2,
-     array >= 0.3 && <0.4,
-     attoparsec >= 0.8.1 && < 0.9,
-     attoparsec-enumerator >= 0.2.0.1 && < 0.3,
-     base >= 4 && < 5,
-     binary >= 0.5 && < 0.6,
-     blaze-builder >= 0.2.1.4 && <0.4,
-     blaze-builder-enumerator >= 0.2.0 && <0.3,
-     bytestring,
-     bytestring-nums >= 0.3.1 && < 0.4,
-     containers,
-     directory-tree,
-     enumerator >= 0.4.7 && <0.5,
-     filepath,
-     haskell98,
-     HUnit >= 1.2 && < 2,
-     MonadCatchIO-transformers >= 0.2.1 && < 0.3,
-     monads-fd >= 0.1.0.4 && <0.2,
-     murmur-hash >= 0.1 && < 0.2,
-     network == 2.3.*,
-     old-locale,
-     parallel > 2,
-     snap-core >= 0.4.1 && <0.5,
-     template-haskell,
-     test-framework >= 0.3.1 && <0.4,
-     test-framework-hunit >= 0.2.5 && < 0.3,
-     test-framework-quickcheck2 >= 0.2.6 && < 0.3,
-     time,
-     transformers,
-     utf8-string >= 0.3.6 && <0.4,
-     vector >= 0.7 && <0.8,
-     vector-algorithms >= 0.4 && <0.5,
-     PSQueue >= 1.1 && <1.2
+  build-depends:
+    QuickCheck >= 2,
+    array >= 0.3 && <0.4,
+    attoparsec >= 0.8.1 && < 0.9,
+    attoparsec-enumerator >= 0.2.0.1 && < 0.3,
+    base >= 4 && < 5,
+    binary >= 0.5 && < 0.6,
+    blaze-builder >= 0.2.1.4 && <0.4,
+    blaze-builder-enumerator >= 0.2.0 && <0.3,
+    bytestring,
+    bytestring-nums >= 0.3.1 && < 0.4,
+    case-insensitive >= 0.2 && < 0.3,
+    containers,
+    directory-tree,
+    enumerator >= 0.4.7 && <0.5,
+    filepath,
+    haskell98,
+    HUnit >= 1.2 && < 2,
+    MonadCatchIO-transformers >= 0.2.1 && < 0.3,
+    monads-fd >= 0.1.0.4 && <0.2,
+    murmur-hash >= 0.1 && < 0.2,
+    network == 2.3.*,
+    old-locale,
+    parallel > 2,
+    snap-core >= 0.5 && <0.6,
+    template-haskell,
+    test-framework >= 0.3.1 && <0.4,
+    test-framework-hunit >= 0.2.5 && < 0.3,
+    test-framework-quickcheck2 >= 0.2.6 && < 0.3,
+    text >= 0.11 && <0.12,
+    time,
+    transformers,
+    vector >= 0.7 && <0.8,
+    vector-algorithms >= 0.4 && <0.5,
+    PSQueue >= 1.1 && <1.2
 
-   if !os(windows)
-     build-depends: unix
+  if !os(windows)
+    build-depends: unix
 
-   if flag(libev)
-     build-depends: hlibev >= 0.2.5 && < 0.3
-     cpp-options: -DLIBEV
+  if flag(libev)
+    build-depends: hlibev >= 0.2.5 && < 0.3
+    cpp-options: -DLIBEV
 
-   if flag(gnutls)
-     extra-libraries: gnutls
-     cpp-options: -DGNUTLS
-     c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
+  if flag(gnutls)
+    extra-libraries: gnutls
+    cpp-options: -DGNUTLS
+    c-sources: ../src/Snap/Internal/Http/Server/gnutls_helpers.c
 
-   if flag(portable) || os(windows)
-     cpp-options: -DPORTABLE
+  if flag(portable) || os(windows)
+    cpp-options: -DPORTABLE
 
-   ghc-options: -O2 -Wall -fwarn-tabs
-                -funbox-strict-fields -threaded
-                -fno-warn-unused-do-bind
-   ghc-prof-options: -prof -auto-all
+  ghc-options: -O2 -Wall -fwarn-tabs
+               -funbox-strict-fields -threaded
+               -fno-warn-unused-do-bind
+  ghc-prof-options: -prof -auto-all
 
 
 Executable benchmark
-   hs-source-dirs:  benchmark common ../src
-   main-is:         Benchmark.hs
+  hs-source-dirs:  benchmark common ../src
+  main-is:         Benchmark.hs
 
-   ghc-options: -O2 -Wall -fwarn-tabs
-                -funbox-strict-fields -threaded
-                -fno-warn-unused-do-bind
+  ghc-options: -O2 -Wall -fwarn-tabs
+               -funbox-strict-fields -threaded
+               -fno-warn-unused-do-bind
 
-   ghc-prof-options: -prof -auto-all
+  ghc-prof-options: -prof -auto-all
 
-   build-depends:
-     base >= 4 && < 5,
-     network == 2.3.*,
-     http-enumerator >= 0.3.1 && <0.4,
-     criterion >= 0.5 && <0.6
+  build-depends:
+    base >= 4 && < 5,
+    network == 2.3.*,
+    http-enumerator >= 0.6.5.3 && <0.7,
+    criterion >= 0.5 && <0.6
diff --git a/test/suite/Test/Blackbox.hs b/test/suite/Test/Blackbox.hs
--- a/test/suite/Test/Blackbox.hs
+++ b/test/suite/Test/Blackbox.hs
@@ -15,6 +15,7 @@
 import qualified Data.ByteString.Char8 as S
 import           Data.ByteString.Char8 (ByteString)
 import qualified Data.ByteString.Lazy.Char8 as L
+import           Data.CaseInsensitive (CI)
 import           Data.Int
 import           Data.List
 import           Data.Monoid
@@ -59,6 +60,7 @@
 
 
 ------------------------------------------------------------------------------
+slowTestOptions :: Bool -> TestOptions' Maybe
 slowTestOptions ssl =
     if ssl
       then mempty { topt_maximum_generated_tests = Just 75 }
@@ -79,7 +81,8 @@
 startTestServer port sslport backend = do
     let cfg = setAccessLog (Just $ "ts-access." ++ show backend ++ ".log") .
               setErrorLog  (Just $ "ts-error." ++ show backend ++ ".log")  .
-              addListen    (ListenHttp "*" port)                           .
+              setBind      "*"                                             .
+              setPort      port                                            .
               setBackend   backend                                         .
               setDefaultTimeout 10                                         .
               setVerbose   False                                           $
@@ -87,8 +90,10 @@
 
     let cfg' = case sslport of
                 Nothing -> cfg
-                Just p  -> addListen
-                           (ListenHttps "*" p "cert.pem" "key.pem")
+                Just p  -> setSSLPort p          .
+                           setSSLBind "*"        .
+                           setSSLCert "cert.pem" .
+                           setSSLKey  "key.pem"  $
                            cfg
 
     mvar <- newEmptyMVar
@@ -109,9 +114,8 @@
                ++ "://127.0.0.1:" ++ show port ++ "/pong"
     debug $ "URI is: '" ++ uri ++ "', calling simpleHttp"
 
-    rsp <- HTTP.simpleHttp uri `catch` (\(e::SomeException) -> do
-               debug $ "simpleHttp threw exception: " ++ show e
-               throwIO e)
+    rsp <- fetch uri
+
     debug $ "response was " ++ show rsp
     return $ S.concat $ L.toChunks rsp
 
@@ -156,19 +160,13 @@
         let uri = (if ssl then "https" else "http")
                   ++ "://127.0.0.1:" ++ show port ++ "/echo"
 
-        req0 <- QC.run $ HTTP.parseUrl uri
-        let req = req0 { HTTP.requestBody = txt
-                       , HTTP.method = "POST" }
-
-        rsp <- QC.run $ HTTP.httpLbs req
-        let doc = HTTP.responseBody rsp
-
+        doc <- QC.run $ post uri txt []
         QC.assert $ txt == doc
 
 
 ------------------------------------------------------------------------------
 testFileUpload :: Bool -> Int -> String -> Test
-testFileUpload ssl port name = 
+testFileUpload ssl port name =
     plusTestOptions (slowTestOptions ssl) $
     testProperty (name ++ "/blackbox/upload") $
     QC.mapSize (if ssl then min 100 else min 300) $
@@ -220,14 +218,8 @@
         let uri = (if ssl then "https" else "http")
                   ++ "://127.0.0.1:" ++ show port ++ "/upload/handle"
 
-        req0 <- QC.run $ HTTP.parseUrl uri
-        let req = req0 { HTTP.requestBody = body kvps
-                       , HTTP.method = "POST"
-                       , HTTP.requestHeaders = hdrs }
-
         let txt = response kvps
-        rsp <- QC.run $ HTTP.httpLbs req
-        let doc = HTTP.responseBody rsp
+        doc <- QC.run $ post uri (body kvps) hdrs
 
         when (txt /= doc) $ QC.run $ do
                      L.putStrLn "expected:"
@@ -253,13 +245,8 @@
         let uri = (if ssl then "https" else "http")
                   ++ "://127.0.0.1:" ++ show port ++ "/rot13"
 
-        req0 <- QC.run $ HTTP.parseUrl uri
-        let req = req0 { HTTP.requestBody = L.fromChunks [txt]
-                       , HTTP.method = "POST" }
-
-        rsp <- QC.run $ HTTP.httpLbs req
-        let doc = S.concat $ L.toChunks $ HTTP.responseBody rsp
-
+        doc <- QC.run $ liftM (S.concat . L.toChunks)
+                      $ post uri (L.fromChunks [txt]) []
         QC.assert $ txt == rot13 doc
 
 
@@ -379,3 +366,46 @@
 ------------------------------------------------------------------------------
 seconds :: Int
 seconds = (10::Int) ^ (6::Int)
+
+
+------------------------------------------------------------------------------
+parseURL :: String -> IO (HTTP.Request IO)
+parseURL url = do
+    req <- HTTP.parseUrl url
+    return $ req { HTTP.checkCerts = const $ return True }
+
+
+------------------------------------------------------------------------------
+fetchReq :: HTTP.Request IO -> IO (L.ByteString)
+fetchReq req = go `catch` (\(e::SomeException) -> do
+                 debug $ "simpleHttp threw exception: " ++ show e
+                 throwIO e)
+  where
+    go = do
+        rsp <- HTTP.withManager $ HTTP.httpLbs req
+        return $ HTTP.responseBody rsp
+
+
+------------------------------------------------------------------------------
+fetch :: String -> IO (L.ByteString)
+fetch url = do
+    req <- parseURL url `catch` (\(e::SomeException) -> do
+                 debug $ "parseURL threw exception: " ++ show e
+                 throwIO e)
+    fetchReq req
+
+
+------------------------------------------------------------------------------
+post :: String
+     -> L.ByteString
+     -> [(CI ByteString, ByteString)]
+     -> IO (L.ByteString)
+post url body hdrs = do
+    req <- parseURL url `catch` (\(e::SomeException) -> do
+                 debug $ "parseURL threw exception: " ++ show e
+                 throwIO e)
+    fetchReq $ req { HTTP.requestBody = HTTP.RequestBodyLBS body
+                   , HTTP.method = "POST"
+                   , HTTP.requestHeaders = hdrs }
+
+
diff --git a/test/suite/TestSuite.hs b/test/suite/TestSuite.hs
--- a/test/suite/TestSuite.hs
+++ b/test/suite/TestSuite.hs
@@ -8,7 +8,7 @@
 import           Control.Concurrent.MVar
 import           Control.Monad
 import           Prelude hiding (catch)
-import qualified Network.HTTP.Enumerator as HTTP
+import           Network (withSocketsDo)
 import           Test.Framework (defaultMain, testGroup)
 import           System.Environment
 import           Snap.Http.Server.Config
@@ -48,7 +48,7 @@
 
 
 main :: IO ()
-main = HTTP.withHttpEnumerator $ do
+main = withSocketsDo $ do
     sp <- getStartPort
     let bends = backends sp
     tinfos <- forM bends $ \(port,sslport,b) ->
