Support checking presence of content at a http url that redirects to a ftp url.

This commit is contained in:
Joey Hess 2016-07-12 16:30:36 -04:00
parent 604565ae66
commit 79704528c0
Failed to extract signature
5 changed files with 57 additions and 21 deletions

View file

@ -18,6 +18,8 @@ git-annex (6.20160614) UNRELEASED; urgency=medium
* uninit: Fix crash due to trying to write to deleted keys db.
Reversion introduced by v6 mode support, affects v5 too.
* Fix a similar crash when the webapp is used to delete a repository.
* Support checking presence of content at a http url that redirects to
a ftp url.
-- Joey Hess <id@joeyh.name> Mon, 13 Jun 2016 21:52:24 -0400

View file

@ -30,7 +30,7 @@ import Remote.Helper.Http
import qualified Remote.Helper.Chunked.Legacy as Legacy
import Creds
import Utility.Metered
import Utility.Url (URLString)
import Utility.Url (URLString, matchStatusCodeException)
import Annex.UUID
import Remote.WebDAV.DavLocation
@ -270,12 +270,6 @@ existsDAV l = inLocation l check `catchNonAsync` (\e -> return (Left $ show e))
(const $ ispresent False)
ispresent = return . Right
matchStatusCodeException :: (Status -> Bool) -> HttpException -> Maybe HttpException
matchStatusCodeException want e@(StatusCodeException s _ _)
| want s = Just e
| otherwise = Nothing
matchStatusCodeException _ _ = Nothing
-- Ignores any exceptions when performing a DAV action.
safely :: DAVT IO a -> DAVT IO (Maybe a)
safely = eitherToMaybe <$$> tryNonAsync

View file

@ -25,7 +25,8 @@ module Utility.Url (
assumeUrlExists,
download,
downloadQuiet,
parseURIRelaxed
parseURIRelaxed,
matchStatusCodeException,
) where
import Common
@ -126,6 +127,7 @@ data UrlInfo = UrlInfo
, urlSize :: Maybe Integer
, urlSuggestedFile :: Maybe FilePath
}
deriving (Show)
assumeUrlExists :: UrlInfo
assumeUrlExists = UrlInfo True Nothing Nothing
@ -135,7 +137,14 @@ assumeUrlExists = UrlInfo True Nothing Nothing
getUrlInfo :: URLString -> UrlOptions -> IO UrlInfo
getUrlInfo url uo = case parseURIRelaxed url of
Just u -> case parseUrl (show u) of
Just req -> existsconduit req `catchNonAsync` const dne
Just req -> catchJust
-- When http redirects to a protocol which
-- conduit does not support, it will throw
-- a StatusCodeException with found302.
(matchStatusCodeException (== found302))
(existsconduit req)
(const (existscurl u))
`catchNonAsync` (const dne)
-- http-conduit does not support file:, ftp:, etc urls,
-- so fall back to reading files and using curl.
Nothing
@ -147,18 +156,7 @@ getUrlInfo url uo = case parseURIRelaxed url of
sz <- getFileSize' f stat
found (Just sz) Nothing
Nothing -> dne
| Build.SysConfig.curl -> do
output <- catchDefaultIO "" $
readProcess "curl" $ toCommand curlparams
let len = extractlencurl output
let good = found len Nothing
case lastMaybe (lines output) of
Just ('2':_:_) -> good
-- don't try to parse ftp status
-- codes; if curl got a length,
-- it's good
_ | "ftp" `isInfixOf` uriScheme u && isJust len -> good
_ -> dne
| Build.SysConfig.curl -> existscurl u
| otherwise -> dne
Nothing -> dne
where
@ -201,6 +199,23 @@ getUrlInfo url uo = case parseURIRelaxed url of
liftIO $ closeManager mgr
return ret
existscurl u = do
output <- catchDefaultIO "" $
readProcess "curl" $ toCommand curlparams
let len = extractlencurl output
let good = found len Nothing
let isftp = or
[ "ftp" `isInfixOf` uriScheme u
-- Check to see if http redirected to ftp.
, "Location: ftp://" `isInfixOf` output
]
case lastMaybe (lines output) of
Just ('2':_:_) -> good
-- don't try to parse ftp status codes; if curl
-- got a length, it's good
_ | isftp && isJust len -> good
_ -> dne
-- Parse eg: attachment; filename="fname.ext"
-- per RFC 2616
contentDispositionFilename :: String -> Maybe FilePath
@ -324,3 +339,13 @@ hContentLength = "Content-Length"
hUserAgent :: CI.CI B.ByteString
hUserAgent = "User-Agent"
#endif
{- Use with eg:
-
- > catchJust (matchStatusCodeException (== notFound404))
-}
matchStatusCodeException :: (Status -> Bool) -> HttpException -> Maybe HttpException
matchStatusCodeException want e@(StatusCodeException s _ _)
| want s = Just e
| otherwise = Nothing
matchStatusCodeException _ _ = Nothing

View file

@ -127,3 +127,5 @@ Logging in as anonymous ...
"""]]
[[!meta author=yoh]]
> [[fixed|done]] --[[Joey]]

View file

@ -0,0 +1,13 @@
[[!comment format=mdwn
username="joey"
subject="""comment 1"""
date="2016-07-12T20:00:49Z"
content="""
This only affects http to ftp redirects, because there's a special hack
in place to use curl to check if a ftp url exists.
Seems that http-conduit throws a StatusCodeException with statusCode = 302
when it is redirected to a protocol that it does not support, such as ftp.
So, it can catch that exception and fall back to curl.
"""]]