moduleNetwork.HTTP.Conduit.Browser(BrowserState,BrowserAction,browse,makeRequest,defaultState,getBrowserState,setBrowserState,withBrowserState,getMaxRedirects,setMaxRedirects,getMaxRetryCount,setMaxRetryCount,getAuthorities,setAuthorities,getCookieFilter,setCookieFilter,getCookieJar,setCookieJar,getCurrentProxy,setCurrentProxy,getUserAgent,setUserAgent,getManager,setManager)whereimportqualifiedData.ByteStringasBSimportControl.Monad.StateimportControl.ExceptionimportqualifiedControl.Exception.LiftedasLEimportData.ConduitimportPreludehiding(catch)importqualifiedNetwork.HTTP.TypesasHTimportData.Time.Clock(getCurrentTime,UTCTime)importData.CaseInsensitive(mk)importData.ByteString.UTF8(fromString)importData.List(partition)importWeb.Cookie(parseSetCookie)importData.Default(def)importData.Maybe(catMaybes)importNetwork.HTTP.Conduit.Cookieshiding(updateCookieJar)importNetwork.HTTP.Conduit.RequestimportNetwork.HTTP.Conduit.ResponseimportNetwork.HTTP.Conduit.ManagerimportqualifiedNetwork.HTTP.ConduitasHCdataBrowserState=BrowserState{maxRedirects::Int,maxRetryCount::Int,authorities::Request(ResourceTIO)->Maybe(BS.ByteString,BS.ByteString),cookieFilter::Request(ResourceTIO)->Cookie->IOBool,cookieJar::CookieJar,currentProxy::MaybeProxy,userAgent::BS.ByteString,manager::Manager}defaultState::Manager->BrowserStatedefaultStatem=BrowserState{maxRedirects=10,maxRetryCount=1,authorities=\_->Nothing,cookieFilter=\__->returnTrue,cookieJar=def,currentProxy=Nothing,userAgent=fromString"http-conduit",manager=m}typeBrowserAction=StateTBrowserState(ResourceTIO)-- | Do the browser action with the given managerbrowse::Manager->BrowserActiona->ResourceTIOabrowsemact=evalStateTact(defaultStatem)-- | Make a request, using all the state in the current BrowserStatemakeRequest::Request(ResourceTIO)->BrowserAction(Response(Source(ResourceTIO)BS.ByteString))makeRequestrequest=doBrowserState{maxRetryCount=max_retry_count,currentProxy=current_proxy,userAgent=user_agent}<-getretryHelper(applyUserAgentuser_agent$request{redirectCount=0,proxy=current_proxy,checkStatus=\__->Nothing})max_retry_countNothingwhereretryHelperrequest'retry_counte|retry_count==0=caseeofJuste'->throwe'Nothing->throwTooManyRedirects|otherwise=doBrowserState{maxRedirects=max_redirects}<-getresp<-LE.catch(runRedirectionChainrequest'max_redirects)(\e'->retryHelperrequest'(retry_count-1)(Just(e'::HttpException)))letcode=HT.statusCode$HC.responseStatusrespifcode<200||code>=300thenretryHelperrequest'(retry_count-1)(Just$HC.StatusCodeException(HC.responseStatusresp)(HC.responseHeadersresp))elsereturnresprunRedirectionChainrequest'redirect_count|redirect_count==0=throwTooManyRedirects|otherwise=dos@(BrowserState{manager=manager',authorities=auths,cookieJar=cookie_jar,cookieFilter=cookie_filter})<-getnow<-liftIOgetCurrentTimelet(request'',cookie_jar')=insertCookiesIntoRequest(applyAuthoritiesauthsrequest')(evictExpiredCookiescookie_jarnow)nowres<-lift$HC.httprequest''manager'(cookie_jar'',response)<-liftIO$updateCookieJarresrequest''nowcookie_jar'cookie_filterput$s{cookieJar=cookie_jar''}letcode=HT.statusCode(HC.responseStatusresponse)ifcode>=300&&code<400thenrunRedirectionChain(caseHC.getRedirectedRequestrequest''(responseHeadersresponse)codeofJusta->aNothing->throwHC.UnparseableRedirect)(redirect_count-1)elsereturnresapplyAuthoritiesauthsrequest'=caseauthsrequest'ofJust(user,pass)->applyBasicAuthuserpassrequest'Nothing->request'applyUserAgentuarequest'=request'{requestHeaders=(k,ua):hs}wherehs=filter((/=k).fst)$requestHeadersrequest'k=mk$fromString"User-Agent"updateCookieJar::Responsea->Request(ResourceTIO)->UTCTime->CookieJar->(Request(ResourceTIO)->Cookie->IOBool)->IO(CookieJar,Responsea)updateCookieJarresponserequest'nowcookie_jarcookie_filter=dofiltered_cookies<-filterM(cookie_filterrequest')$catMaybes$map(\sc->generateCookiescrequest'nowTrue)set_cookiesreturn(cookieJar'filtered_cookies,response{HC.responseHeaders=other_headers})where(set_cookie_headers,other_headers)=partition((==(mk$fromString"Set-Cookie")).fst)$HC.responseHeadersresponseset_cookie_data=mapsndset_cookie_headersset_cookies=mapparseSetCookieset_cookie_datacookieJar'=foldl(\cjc->insertCheckedCookieccjTrue)cookie_jar-- | You can save and restore the state at willgetBrowserState::BrowserActionBrowserStategetBrowserState=getsetBrowserState::BrowserState->BrowserAction()setBrowserState=putwithBrowserState::BrowserState->BrowserActiona->BrowserActionawithBrowserStatesa=docurrent<-getputsout<-aputcurrentreturnout-- | The number of redirects to allowgetMaxRedirects::BrowserActionIntgetMaxRedirects=get>>=\a->return$maxRedirectsasetMaxRedirects::Int->BrowserAction()setMaxRedirectsb=get>>=\a->puta{maxRedirects=b}-- | The number of times to retry a failed connectiongetMaxRetryCount::BrowserActionIntgetMaxRetryCount=get>>=\a->return$maxRetryCountasetMaxRetryCount::Int->BrowserAction()setMaxRetryCountb=get>>=\a->puta{maxRetryCount=b}-- | A user-provided function that provides optional authorities.-- This function gets run on all requests before they get sent out.-- The output of this function is applied to the request.getAuthorities::BrowserAction(Request(ResourceTIO)->Maybe(BS.ByteString,BS.ByteString))getAuthorities=get>>=\a->return$authoritiesasetAuthorities::(Request(ResourceTIO)->Maybe(BS.ByteString,BS.ByteString))->BrowserAction()setAuthoritiesb=get>>=\a->puta{authorities=b}-- | Each new Set-Cookie the browser encounters will pass through this filter.-- Only cookies that pass the filter (and are already valid) will be allowed into the cookie jargetCookieFilter::BrowserAction(Request(ResourceTIO)->Cookie->IOBool)getCookieFilter=get>>=\a->return$cookieFilterasetCookieFilter::(Request(ResourceTIO)->Cookie->IOBool)->BrowserAction()setCookieFilterb=get>>=\a->puta{cookieFilter=b}-- | All the cookies!getCookieJar::BrowserActionCookieJargetCookieJar=get>>=\a->return$cookieJarasetCookieJar::CookieJar->BrowserAction()setCookieJarb=get>>=\a->puta{cookieJar=b}-- | An optional proxy to send all requests throughgetCurrentProxy::BrowserAction(MaybeProxy)getCurrentProxy=get>>=\a->return$currentProxyasetCurrentProxy::MaybeProxy->BrowserAction()setCurrentProxyb=get>>=\a->puta{currentProxy=b}-- | What string to report our user-agent asgetUserAgent::BrowserActionBS.ByteStringgetUserAgent=get>>=\a->return$userAgentasetUserAgent::BS.ByteString->BrowserAction()setUserAgentb=get>>=\a->puta{userAgent=b}-- | The active manager, managing the connection poolgetManager::BrowserActionManagergetManager=get>>=\a->return$managerasetManager::Manager->BrowserAction()setManagerb=get>>=\a->puta{manager=b}