content ranges implemented

This commit is contained in:
Keagan McClelland
2022-06-27 16:49:07 -06:00
committed by Lucy Cifferello
parent 6127135a4d
commit f578e763ba

View File

@@ -4,9 +4,9 @@
module Handler.Package.V0.S9PK where module Handler.Package.V0.S9PK where
import Data.String.Interpolate.IsString ( import Conduit (awaitForever, (.|))
i, import Data.Conduit.Binary (sourceFileRange)
) import Data.String.Interpolate.IsString (i)
import Data.Text qualified as T import Data.Text qualified as T
import Database.Queries ( import Database.Queries (
createMetric, createMetric,
@@ -32,30 +32,22 @@ import Lib.Types.Core (
S9PK, S9PK,
) )
import Lib.Types.Emver (Version (..)) import Lib.Types.Emver (Version (..))
import Network.HTTP.Types (status404) import Network.HTTP.Types (ByteRange (..), hRange, parseByteRanges, status404, status416)
import Startlude ( import Startlude (Applicative (..), Maybe (..), Num ((-)), Text, fmap, foldr, for, liftIO, pure, void, ($), (.), (>>=))
Maybe (..), import System.Directory (getFileSize)
pure,
void,
($),
(.),
(>>=),
)
import System.FilePath (takeBaseName) import System.FilePath (takeBaseName)
import Yesod ( import Yesod (Content (..), TypedContent, YesodPersist (runDB), lookupHeader, notFound, respond, sendChunkBS, sendResponseStatus, typeOctet)
Content (..),
TypedContent,
YesodPersist (runDB),
notFound,
respond,
sendResponseStatus,
typeOctet,
)
import Yesod.Core (logError) import Yesod.Core (logError)
getAppR :: S9PK -> Handler TypedContent getAppR :: S9PK -> Handler TypedContent
getAppR file = do getAppR file = do
mRange <-
lookupHeader hRange >>= \case
Nothing -> pure Nothing
Just bs -> case parseByteRanges bs of
Nothing -> sendResponseStatus status416 ("Range Not Satisfiable" :: Text)
Just ranges -> pure $ Just ranges
let pkg = PkgId . T.pack $ takeBaseName (show file) let pkg = PkgId . T.pack $ takeBaseName (show file)
osVersion <- getOsVersionQuery osVersion <- getOsVersionQuery
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
@@ -70,7 +62,17 @@ getAppR file = do
getPackage pkg version >>= \case getPackage pkg version >>= \case
Nothing -> sendResponseStatus status404 (NotFoundE [i|#{pkg}@#{version}|]) Nothing -> sendResponseStatus status404 (NotFoundE [i|#{pkg}@#{version}|])
Just a -> pure a Just a -> pure a
respond typeOctet $ ContentFile pkgPath Nothing case mRange of
Nothing -> respond typeOctet $ ContentFile pkgPath Nothing
Just ranges -> do
composite <- fmap (foldr (*>) (pure ())) $
for ranges $ \case
ByteRangeFrom start -> pure $ sourceFileRange pkgPath (Just start) Nothing
ByteRangeFromTo start end -> pure $ sourceFileRange pkgPath (Just start) (Just end)
ByteRangeSuffix suffix -> do
sz <- liftIO $ getFileSize pkgPath
pure $ sourceFileRange pkgPath (Just $ sz - suffix) Nothing
respond typeOctet $ ContentSource $ composite .| awaitForever sendChunkBS
recordMetrics :: PkgId -> Version -> Handler () recordMetrics :: PkgId -> Version -> Handler ()