{-# LANGUAGE OverloadedStrings #-}{-# LANGUAGE FlexibleContexts #-}{-# LANGUAGE CPP #-}-- | This module contains everything you need to initiate HTTP connections. If-- you want a simple interface based on URLs, you can use 'simpleHttp'. If you-- want raw power, 'http' is the underlying workhorse of this package. Some-- examples:---- > -- Just download an HTML document and print it.-- > import Network.HTTP.Conduit-- > import qualified Data.ByteString.Lazy as L-- >-- > main = simpleHttp "http://www.haskell.org/" >>= L.putStr---- This example uses interleaved IO to write the response body to a file in-- constant memory space.---- > import Data.Conduit.Binary (sinkFile)-- > import Network.HTTP.Conduit-- > import qualified Data.Conduit as C-- >-- > main :: IO ()-- > main = do-- > request <- parseUrl "http://google.com/"-- > withManager $ \manager -> do-- > Response _ _ _ src <- http request manager-- > src C.$$+- sinkFile "google.html"---- The following headers are automatically set by this module, and should not-- be added to 'requestHeaders':---- * Content-Length---- Note: In previous versions, the Host header would be set by this module in-- all cases. Starting from 1.6.1, if a Host header is present in-- @requestHeaders@, it will be used in place of the header this module would-- have generated. This can be useful for calling a server which utilizes-- virtual hosting.---- Any network code on Windows requires some initialization, and the network-- library provides withSocketsDo to perform it. Therefore, proper usage of-- this library will always involve calling that function at some point. The-- best approach is to simply call them at the beginning of your main function,-- such as:---- > import Network.HTTP.Conduit-- > import qualified Data.ByteString.Lazy as L-- > import Network (withSocketsDo)-- >-- > main = withSocketsDo-- > $ simpleHttp "http://www.haskell.org/" >>= L.putStr-- >-- > Cookies are implemented according to RFC 6265.---- Note that by default, the functions in this package will throw exceptions-- for non-2xx status codes. If you would like to avoid this, you should use-- 'checkStatus', e.g.:---- > import Data.Conduit.Binary (sinkFile)-- > import Network.HTTP.Conduit-- > import qualified Data.Conduit as C-- > import Network-- >-- > main :: IO ()-- > main = withSocketsDo $ do-- > request' <- parseUrl "http://www.yesodweb.com/does-not-exist"-- > let request = request' { checkStatus = \_ _ -> Nothing }-- > res <- withManager $ httpLbs request-- > print resmoduleNetwork.HTTP.Conduit(-- * Perform a requestsimpleHttp,httpLbs,http-- * Datatypes,Proxy(..),RequestBody(..),Response(..)-- ** Request,Request,def,method,secure,clientCertificates,host,port,path,queryString,requestHeaders,requestBody,proxy,socksProxy,rawBody,decompress,redirectCount,checkStatus,responseTimeout-- * Manager,Manager,newManager,closeManager,withManager,withManagerSettings-- ** Settings,ManagerSettings,managerConnCount,managerCheckCerts,managerCertStore-- *** Defaults,defaultCheckCerts-- * Cookies,Cookie(..),CookieJar,createCookieJar,destroyCookieJar,updateCookieJar,receiveSetCookie,generateCookie,insertCheckedCookie,insertCookiesIntoRequest,computeCookieString,evictExpiredCookies-- * Utility functions,parseUrl,applyBasicAuth,addProxy,lbsResponse,getRedirectedRequest-- * Decompression predicates,alwaysDecompress,browserDecompress-- * Request bodies,urlEncodedBody-- * Exceptions,HttpException(..)#if DEBUG-- * Debug,printOpenSockets#endif)whereimportqualifiedData.ByteStringasSimportqualifiedData.ByteString.LazyasLimportqualifiedNetwork.HTTP.TypesasWimportData.Default(def)importControl.Exception.Lifted(throwIO)importControl.Monad((<=<))importControl.Monad.IO.Class(MonadIO(liftIO))importControl.Monad.Trans.ResourceimportControl.Monad.Trans.State(get,put,evalStateT)importControl.Monad.Trans(lift)importControl.Exception(fromException,toException)importqualifiedData.ConduitasCimportqualifiedData.Conduit.BinaryasCBimportqualifiedData.Conduit.InternalasCIimportData.Conduit.Blaze(builderToByteString)importControl.Exception.Lifted(try,SomeException)importData.Time.ClockimportNetwork.HTTP.Conduit.RequestimportNetwork.HTTP.Conduit.ResponseimportNetwork.HTTP.Conduit.ManagerimportNetwork.HTTP.Conduit.ConnInfoimportNetwork.HTTP.Conduit.CookiesimportNetwork.HTTP.Conduit.Internal(httpRedirect)-- | The most low-level function for initiating an HTTP request.---- The first argument to this function gives a full specification-- on the request: the host to connect to, whether to use SSL,-- headers, etc. Please see 'Request' for full details. The-- second argument specifies which 'Manager' should be used.---- This function then returns a 'Response' with a-- 'C.Source'. The 'Response' contains the status code-- and headers that were sent back to us, and the-- 'C.Source' contains the body of the request. Note-- that this 'C.Source' allows you to have fully-- interleaved IO actions during your HTTP download, making it-- possible to download very large responses in constant memory.-- You may also directly connect the returned 'C.Source'-- into a 'C.Sink', perhaps a file or another socket.---- Note: Unlike previous versions, this function will perform redirects, as-- specified by the 'redirectCount' setting.http::(MonadResourcem,MonadBaseControlIOm)=>Requestm->Manager->m(Response(C.ResumableSourcemS.ByteString))httpreq0manager=dores@(Responsestatus_versionhsbody)<-ifredirectCountreq0==0thenhttpRawreq0managerelsego(redirectCountreq0)req0defcasecheckStatusreq0statushsofNothing->returnresJustexc->doexc'<-casefromExceptionexcofJust(StatusCodeExceptionshdrs)->dolbs<-bodyC.$$+-CB.take1024return$toException$StatusCodeExceptions$hdrs++[("X-Response-Body-Start",S.concat$L.toChunkslbs)]_->doletCI.ResumableSource_final=bodyfinalreturnexcliftIO$throwIOexc'wheregocountreq'''cookie_jar'''=(`evalStateT`cookie_jar''')$httpRedirectcount(\req''->docookie_jar''<-getnow<-liftIOgetCurrentTimelet(req',cookie_jar')=insertCookiesIntoRequestreq''(evictExpiredCookiescookie_jar''now)nowres<-lift$httpRawreq'managerlet(cookie_jar,_)=updateCookieJarresreq'nowcookie_jar'putcookie_jarletmreq=getRedirectedRequestreq'(responseHeadersres)(W.statusCode(responseStatusres))return(res,mreq))liftreq'''-- | Get a 'Response' without any redirect following.httpRaw::(MonadBaseControlIOm,MonadResourcem)=>Requestm->Manager->m(Response(C.ResumableSourcemS.ByteString))httpRawreqm=do(connRelease,ci,isManaged)<-getConnreqmletsrc=connSourceci-- Originally, we would only test for exceptions when sending the request,-- not on calling @getResponse@. However, some servers seem to close-- connections after accepting the request headers, so we need to check for-- exceptions in both.ex<-try'$dorequestBuilderreqC.$$builderToByteStringC.=$connSinkcigetResponseconnReleasereqsrccase(ex,isManaged)of-- Connection was reused, and might be been closed. Try again(Left_,Reused)->doconnReleaseDontReusehttpreqm-- Not reused, so this is a real exception(Lefte,Fresh)->liftIO$throwIOe-- Everything went ok, so the connection is good. If any exceptions get-- thrown in the response body, just throw them as normal.(Rightx,_)->returnxwheretry'::MonadBaseControlIOm=>ma->m(EitherSomeExceptiona)try'=try-- | Download the specified 'Request', returning the results as a 'Response'.---- This is a simplified version of 'http' for the common case where you simply-- want the response data as a simple datatype. If you want more power, such as-- interleaved actions on the response body during download, you'll need to use-- 'http' directly. This function is defined as:---- @httpLbs = 'lbsResponse' <=< 'http'@---- Even though the 'Response' contains a lazy bytestring, this-- function does /not/ utilize lazy I/O, and therefore the entire-- response body will live in memory. If you want constant memory-- usage, you'll need to use @conduit@ packages's-- 'C.Source' returned by 'http'.---- Note: Unlike previous versions, this function will perform redirects, as-- specified by the 'redirectCount' setting.httpLbs::(MonadBaseControlIOm,MonadResourcem)=>Requestm->Manager->m(ResponseL.ByteString)httpLbsr=lbsResponse<=<httpr-- | Download the specified URL, following any redirects, and-- return the response body.---- This function will 'throwIO' an 'HttpException' for any-- response with a non-2xx status code (besides 3xx redirects up-- to a limit of 10 redirects). It uses 'parseUrl' to parse the-- input. This function essentially wraps 'httpLbs'.---- Note: Even though this function returns a lazy bytestring, it-- does /not/ utilize lazy I/O, and therefore the entire response-- body will live in memory. If you want constant memory usage,-- you'll need to use the @conduit@ package and 'http' directly.---- Note: This function creates a new 'Manager'. It should be avoided-- in production code.simpleHttp::MonadIOm=>String->mL.ByteStringsimpleHttpurl=liftIO$withManager$\man->dourl'<-liftIO$parseUrlurlfmapresponseBody$httpLbsurl'man