feat: add pre-http-request-hooks config entry and handle it

This commit is contained in:
Oleg Lebedev 2022-12-02 16:01:13 +11:00
parent ca42068bdc
commit 249db93b73
No known key found for this signature in database
GPG Key ID: 3C15FD646FF47549
2 changed files with 49 additions and 0 deletions

View File

@ -116,6 +116,26 @@ struct curlFileTransfer : public FileTransfer
for (auto it = request.headers.begin(); it != request.headers.end(); ++it){
requestHeaders = curl_slist_append(requestHeaders, fmt("%s: %s", it->first, it->second).c_str());
}
for (auto &[host, prog] : fileTransferSettings.preHTTPRequestHooks.get())
{
if (hasPrefix(request.uri, fmt("https://%s/", host)) || hasPrefix(request.uri, fmt("http://%s/", host)))
{
auto verb = request.data ? "upload" : "download";
debug("pre-http-request-hooks: '%s' for '%s' (%d)", prog, request.uri, verb);
auto lines = runProgram(prog, false, Strings({ request.uri, verb }));
auto lastPos = std::string::size_type{0};
for (auto nlPos = lines.find('\n'); nlPos != std::string::npos; nlPos = lines.find('\n', lastPos))
{
auto line = lines.substr(lastPos, nlPos - lastPos);
lastPos = nlPos + 1;
auto hn = line.substr(0, line.find(':'));
debug("add header: '%s: *****' to '%s' (%d)", hn, request.uri, verb);
requestHeaders = curl_slist_append(requestHeaders, line.c_str());
}
break;
}
}
}
~TransferItem()

View File

@ -26,6 +26,35 @@ struct FileTransferSettings : Config
)",
{"binary-caches-parallel-connections"}};
Setting<StringMap> preHTTPRequestHooks{this, {}, "pre-http-request-hooks",
R"(
Optional. A whitespace-separated list of tuples (`host=<path to a program>`) where
the program can set extra URL-specific HTTP headers. This is used for URLs
that can't be accessed publically.
The hook is passed wth the resource URL and the verb (`upload` or `download`).
It can then add https headers to the HTTP request by send them to stdout.
When using the nix-daemon, the daemon executes the hook as `root`.
If the nix-daemon is not involved, the hook runs as the user
executing the nix-build.
Example:
`#!/usr/bin/env bash
source /my/lib.sh
url=$1
verb=$2
host=$(parse_host ${url})
token=$(get_cached_CF_token_for ${url} ${verb})
echo Cookie: CF_Authorization=${token}; Domain=${host}; Secure; HttpOnly
echo Origin: ${host}
`.
)"};
Setting<unsigned long> connectTimeout{
this, 0, "connect-timeout",
R"(