Fix /log/ endpoint

The old logic would fail to return a result if a later
substituter didn't have the log file, even if an older

This also simplifies the logic.
This commit is contained in:
Gabriella Gonzalez 2022-07-01 12:29:28 -07:00
parent c8d0b47a7a
commit dbf735e77f
3 changed files with 37 additions and 55 deletions

View File

@ -176,30 +176,26 @@ void dumpPath(char const * const hashPart, struct string * const output) {
} }
} }
void dumpLog(char const * const hashPart, struct string * const output) { void dumpLog(char const * const baseName, struct string * const output) {
ref<Store> store = getStore(); ref<Store> store = getStore();
std::optional<StorePath> storePath = StorePath storePath(baseName);
store->queryPathFromHashPart(hashPart);
if (storePath.has_value()) { auto subs = getDefaultSubstituters();
auto subs = getDefaultSubstituters();
subs.push_front(store); subs.push_front(store);
for (auto & sub : subs) { *output = emptyString;
LogStore * logStore = dynamic_cast<LogStore *>(&*sub);
std::optional<std::string> log = logStore->getBuildLog(storePath.value()); for (auto & sub : subs) {
LogStore * logStore = dynamic_cast<LogStore *>(&*sub);
if (log.has_value()) { std::optional<std::string> log = logStore->getBuildLog(storePath);
copyString(log.value(), output);
} else { if (log.has_value()) {
*output = emptyString; copyString(log.value(), output);
}
} }
} else {
*output = emptyString;
} }
} }
} }

View File

@ -88,23 +88,26 @@ makeApplication ApplicationOptions{..} request respond = do
done response done response
let invalidPath = do
let headers = [ ("Content-Type", "text/plain") ]
let builder = "Invalid path.\n"
let response =
Wai.responseBuilder
Types.status400
headers
builder
done response
result <- Except.runExceptT do result <- Except.runExceptT do
let rawPath = Wai.rawPathInfo request let rawPath = Wai.rawPathInfo request
if | Just prefix <- ByteString.stripSuffix ".narinfo" rawPath if | Just prefix <- ByteString.stripSuffix ".narinfo" rawPath
, Just hashPart <- ByteString.stripPrefix "/" prefix -> do , Just hashPart <- ByteString.stripPrefix "/" prefix -> do
Monad.unless (ByteString.length hashPart == 32 && validHashPart hashPart) do Monad.unless (ByteString.length hashPart == 32 && validHashPart hashPart) do
let headers = [ ("Content-Type", "text/plain") ] invalidPath
let builder = "Invalid hash part.\n"
let response =
Wai.responseBuilder
Types.status400
headers
builder
done response
maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart) maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart)
@ -219,30 +222,10 @@ makeApplication ApplicationOptions{..} request respond = do
return (interior, Nothing) return (interior, Nothing)
| otherwise -> do | otherwise -> do
let headers = [ ("Content-Type", "text/plain") ] invalidPath
let builder = "Invalid path component.\n"
let response =
Wai.responseBuilder
Types.status400
headers
builder
done response
Monad.unless (validHashPart hashPart) do Monad.unless (validHashPart hashPart) do
let headers = [ ("Content-Type", "text/plain") ] invalidPath
let builder = "Invalid hash part.\n"
let response =
Wai.responseBuilder
Types.status400
headers
builder
done response
maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart) maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart)
@ -281,11 +264,14 @@ makeApplication ApplicationOptions{..} request respond = do
done response done response
| Just suffix <- ByteString.stripPrefix "/log/" rawPath | Just suffix <- ByteString.stripPrefix "/log/" rawPath -> do
, 32 <= ByteString.length suffix -> do
let hashPart = ByteString.take 32 suffix let hashPart = ByteString.take 32 suffix
maybeBytes <- liftIO (Nix.dumpLog hashPart) Monad.unless (ByteString.length hashPart == 32 && validHashPart hashPart) do
invalidPath
liftIO (print suffix)
maybeBytes <- liftIO (Nix.dumpLog suffix)
bytes <- case maybeBytes of bytes <- case maybeBytes of
Nothing -> noSuchPath Nothing -> noSuchPath

View File

@ -280,10 +280,10 @@ foreign import ccall "dumpLog" dumpLog_
:: CString -> Ptr String_ -> IO () :: CString -> Ptr String_ -> IO ()
dumpLog :: ByteString -> IO (Maybe ByteString) dumpLog :: ByteString -> IO (Maybe ByteString)
dumpLog hashPart = do dumpLog baseName = do
ByteString.useAsCString hashPart \cHashPart -> do ByteString.useAsCString baseName \cBaseName -> do
Foreign.alloca \output -> do Foreign.alloca \output -> do
let open = dumpLog_ cHashPart output let open = dumpLog_ cBaseName output
let close = freeString output let close = freeString output
Exception.bracket_ open close do Exception.bracket_ open close do
string_@String_{ data_} <- peek output string_@String_{ data_} <- peek output