where
bad = fromMaybe (giveup $ "bad url " ++ urlstring) $
Url.parseURIRelaxed $ urlstring
- go url = startingAddUrl urlstring o $ do
+ go url = startingAddUrl urlstring o $
+ if relaxedOption (downloadOptions o)
+ then go' url Url.assumeUrlExists
+ else Url.withUrlOptions (Url.getUrlInfo urlstring) >>= \case
+ Right urlinfo -> go' url urlinfo
+ Left err -> do
+ warning err
+ next $ return False
+ go' url urlinfo = do
pathmax <- liftIO $ fileNameLengthLimit "."
- urlinfo <- if relaxedOption (downloadOptions o)
- then pure Url.assumeUrlExists
- else Url.withUrlOptions $ Url.getUrlInfo urlstring
file <- adjustFile o <$> case fileOption (downloadOptions o) of
Just f -> pure f
Nothing -> case Url.urlSuggestedFile urlinfo of
r <- Remote.claimingUrl url
if Remote.uuid r == webUUID || rawOption (downloadOptions opts)
then do
- urlinfo <- if relaxedOption (downloadOptions opts)
- then pure Url.assumeUrlExists
- else Url.withUrlOptions $
- Url.getUrlInfo url
let dlopts = (downloadOptions opts)
-- force using the filename
-- chosen here
-- don't use youtube-dl
, rawOption = True
}
- maybeToList <$> addUrlFile addunlockedmatcher dlopts url urlinfo f
+ let go urlinfo = maybeToList <$> addUrlFile addunlockedmatcher dlopts url urlinfo f
+ if relaxedOption (downloadOptions opts)
+ then go Url.assumeUrlExists
+ else Url.withUrlOptions (Url.getUrlInfo url) >>= \case
+ Right urlinfo -> go urlinfo
+ Left err -> do
+ warning err
+ return []
else do
res <- tryNonAsync $ maybe
(error $ "unable to checkUrl of " ++ Remote.name r)
{- Checks that an url exists and could be successfully downloaded,
- also checking that its size, if available, matches a specified size.
-
- - The Left error is returned if policy does not allow accessing the url
- - or the url scheme is not supported.
+ - The Left error is returned if policy or the restricted http manager
+ - does not allow accessing the url or the url scheme is not supported.
-}
checkBoth :: URLString -> Maybe Integer -> UrlOptions -> IO (Either String Bool)
checkBoth url expected_size uo = fmap go <$> check url expected_size uo
{- Checks that an url exists and could be successfully downloaded,
- also returning its size and suggested filename if available.
-
- - The Left error is returned if policy does not allow accessing the url
- - or the url scheme is not supported.
+ - The Left error is returned if policy or the restricted http manages
+ - does not allow accessing the url or the url scheme is not supported.
-}
getUrlInfo :: URLString -> UrlOptions -> IO (Either String UrlInfo)
getUrlInfo url uo = case parseURIRelaxed url of
where
go :: URI -> IO (Either String UrlInfo)
go u = case (urlDownloader uo, parseRequest (show u)) of
- (DownloadWithConduit (DownloadWithCurlRestricted r), Just req) -> catchJust
- -- When http redirects to a protocol which
- -- conduit does not support, it will throw
- -- a StatusCodeException with found302
- -- and a Response with the redir Location.
- (matchStatusCodeException (== found302))
- (Right <$> existsconduit req uo)
- (followredir r)
- `catchNonAsync` (const $ return $ Right dne)
+ (DownloadWithConduit (DownloadWithCurlRestricted r), Just req) ->
+ existsconduit r req
(DownloadWithConduit (DownloadWithCurlRestricted r), Nothing)
| isfileurl u -> Right <$> existsfile u
| isftpurl u -> (Right <$> existscurlrestricted r u url ftpport)
extractfilename = contentDispositionFilename . B8.toString
<=< lookup hContentDisposition . responseHeaders
- existsconduit req uo' = do
+ existsconduit r req =
+ let go = catchcrossprotoredir r (existsconduit' req uo)
+ in catchJust matchconnectionrestricted go retconnectionrestricted
+
+ matchconnectionrestricted he@(HttpExceptionRequest _ (InternalException ie)) =
+ case fromException ie of
+ Just (ConnectionRestricted why) -> Just he
+ _ -> Nothing
+ matchconnectionrestricted _ = Nothing
+
+ retconnectionrestricted he@(HttpExceptionRequest _ (InternalException ie)) =
+ case fromException ie of
+ Just (ConnectionRestricted why) -> return (Left why)
+ _ -> throwM he
+ retconnectionrestricted he = throwM he
+
+ existsconduit' req uo' = do
let req' = headRequest (applyRequest uo req)
debugM "url" (show req')
join $ runResourceT $ do
then return $ getBasicAuth uo' (show (getUri req)) >>= \case
Nothing -> return dne
Just (ba, signalsuccess) -> do
- ui <- existsconduit
+ ui <- existsconduit'
(applyBasicAuth' ba req)
(uo' { getBasicAuth = noBasicAuth })
signalsuccess (urlExists ui)
sz <- getFileSize' f stat
found (Just sz) Nothing
Nothing -> return dne
+
+ -- When http server redirects to a protocol which conduit does not
+ -- support, it will throw a StatusCodeException with found302
+ -- and a Response with the redir Location.
+ catchcrossprotoredir r a =
+ catchJust (matchStatusCodeException (== found302))
+ (Right <$> a)
+ (followredir r)
followredir r (HttpExceptionRequest _ (StatusCodeException resp _)) =
case headMaybe $ map decodeBS $ getResponseHeader hLocation resp of