diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 2.2.1
+
+* Add `httpSource` to `Network.HTTP.Simple`
+
 ## 2.2.0.1
 
 * Doc fixes
diff --git a/Network/HTTP/Conduit.hs b/Network/HTTP/Conduit.hs
--- a/Network/HTTP/Conduit.hs
+++ b/Network/HTTP/Conduit.hs
@@ -91,9 +91,13 @@
 -- >      request' <- parseRequest "http://example.com/secret-page"
 -- >      manager <- newManager tlsManagerSettings
 -- >      let request = request' { cookieJar = Just $ createCookieJar [cookie] }
--- >      (fmap Just (httpLbs request manager)) `E.catch`
--- >              (\(StatusCodeException s _ _) ->
--- >                if statusCode s==403 then (putStrLn "login failed" >> return Nothing) else return Nothing)
+-- >      fmap Just (httpLbs request manager) `E.catch`
+-- >              (\ex -> case ex of
+-- >                  HttpExceptionRequest _ (StatusCodeException res _) ->
+-- >                      if statusCode (responseStatus res) == 403
+-- >                        then (putStrLn "login failed" >> return Nothing)
+-- >                        else return Nothing
+-- >                  _ -> E.throw ex)
 --
 -- Any network code on Windows requires some initialization, and the network
 -- library provides withSocketsDo to perform it. Therefore, proper usage of
diff --git a/Network/HTTP/Simple.hs b/Network/HTTP/Simple.hs
--- a/Network/HTTP/Simple.hs
+++ b/Network/HTTP/Simple.hs
@@ -21,6 +21,7 @@
     , httpJSON
     , httpJSONEither
     , httpSink
+    , httpSource
       -- * Types
     , H.Request
     , H.Response
@@ -86,6 +87,7 @@
 import qualified Control.Monad.Catch as Catch
 import qualified Network.HTTP.Types as H
 import Data.Int (Int64)
+import Control.Monad.Trans.Resource (MonadResource)
 
 -- | Perform an HTTP request and return the body as a lazy @ByteString@. Note
 -- that the entire value will be read into memory at once (no lazy I\/O will be
@@ -147,6 +149,46 @@
         (liftIO . H.responseClose)
         (\res -> bodyReaderSource (getResponseBody res)
             C.$$ sink (fmap (const ()) res))
+
+-- | Perform an HTTP request, and get the response body as a Source.
+--
+-- The second argument to this function tells us how to make the
+-- Source from the Response itself. This allows you to perform actions
+-- with the status or headers, for example, in addition to the raw
+-- bytes themselves. If you just care about the response body, you can
+-- use 'getResponseBody' as the second argument here.
+--
+-- @
+-- \{\-# LANGUAGE OverloadedStrings \#\-}
+-- import           Control.Monad.IO.Class       (liftIO)
+-- import           Control.Monad.Trans.Resource (runResourceT)
+-- import           Data.Conduit                 (($$))
+-- import qualified Data.Conduit.Binary          as CB
+-- import qualified Data.Conduit.List            as CL
+-- import           Network.HTTP.Simple
+-- import           System.IO                    (stdout)
+--
+-- main :: IO ()
+-- main =
+--     runResourceT
+--         $ httpSource "http://httpbin.org/robots.txt" getSrc
+--        $$ CB.sinkHandle stdout
+--   where
+--     getSrc res = do
+--         liftIO $ print (getResponseStatus res, getResponseHeaders res)
+--         getResponseBody res
+-- @
+--
+-- @since 2.2.1
+httpSource :: (MonadResource m, MonadIO n)
+           => H.Request
+           -> (H.Response (C.ConduitM i S.ByteString n ())
+                -> C.ConduitM i o m r)
+           -> C.ConduitM i o m r
+httpSource req withRes = do
+    man <- liftIO H.getGlobalManager
+    C.bracketP (H.responseOpen req man) H.responseClose
+        (withRes . fmap bodyReaderSource)
 
 -- | Alternate spelling of 'httpLBS'
 --
diff --git a/http-conduit.cabal b/http-conduit.cabal
--- a/http-conduit.cabal
+++ b/http-conduit.cabal
@@ -1,5 +1,5 @@
 name:            http-conduit
-version:         2.2.0.1
+version:         2.2.1
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
