{"thread":{"id":"60972","subject":"[PATCH] Add unix domain socket support to HTTP transport.","startedAt":"2024-02-21T09:14:26Z","lastAt":"2024-02-23T22:24:35Z","messageCount":7,"participants":["Leslie Cheng via GitGitGadget","Eric Wong","Leslie Cheng","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"489060","messageId":"pull.1681.git.git.1708506863243.gitgitgadget@gmail.com","threadId":"60972","inReplyTo":null,"subject":"[PATCH] Add unix domain socket support to HTTP transport.","fromName":"Leslie Cheng via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-02-21T09:14:23Z","receivedAt":"2024-02-21T09:14:26Z","isPatch":true,"sender":{"key":"leslie.cheng5@gmail.com","avatar":null},"body":"From: Leslie Cheng <leslie.cheng5@gmail.com>\n\nThis changeset introduces an `http.unixSocket` option so that users can\nproxy their git over HTTP remotes to a unix domain socket. In terms of\nwhy, since UDS are local and git already has a local protocol: some\ncorporate environments use a UDS to proxy requests to internal resources\n(ie. source control), so this change would support those use-cases. This\nproxy can occasionally be necessary to attach MFA tokens or client\ncertificates for CLI tools.\n\nThe implementation leverages `--unix-socket` option [0] via the\n`CURLOPT_UNIX_SOCKET_PATH` flag available with libcurl [1].\n\n`GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH` and `NO_UNIX_SOCKETS` were kept\nseparate so that we can spit out better error messages for users if git\nwas compiled with `NO_UNIX_SOCKETS`.\n\n[0] https://curl.se/docs/manpage.html#--unix-socket\n[1] https://curl.se/libcurl/c/CURLOPT_UNIX_SOCKET_PATH.html\n\nSigned-off-by: Leslie Cheng <leslie@lc.fyi>\n---\n    Add unix domain socket support to HTTP transport.\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1681%2Flcfyi%2Flcfyi%2Fadd-unix-socket-support-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1681/lcfyi/lcfyi/add-unix-socket-support-v1\nPull-Request: https://github.com/git/git/pull/1681\n\n Documentation/config/http.txt      |  5 ++\n git-curl-compat.h                  |  7 +++\n http.c                             | 23 +++++++++\n t/t5565-http-unix-domain-socket.sh | 80 ++++++++++++++++++++++++++++++\n 4 files changed, 115 insertions(+)\n create mode 100755 t/t5565-http-unix-domain-socket.sh\n\ndiff --git a/Documentation/config/http.txt b/Documentation/config/http.txt\nindex 2d4e0c9b869..bf48cbd599a 100644\n--- a/Documentation/config/http.txt\n+++ b/Documentation/config/http.txt\n@@ -277,6 +277,11 @@ http.followRedirects::\n \tthe base for the follow-up requests, this is generally\n \tsufficient. The default is `initial`.\n \n+http.unixSocket::\n+\tConnect through this Unix domain socket via HTTP, instead of using the\n+\tnetwork. If set, this config takes precendence over `http.proxy` and\n+\tis incompatible with the proxy options (see `curl(1)`).\n+\n http.<url>.*::\n \tAny of the http.* options above can be applied selectively to some URLs.\n \tFor a config key to match a URL, each element of the config key is\ndiff --git a/git-curl-compat.h b/git-curl-compat.h\nindex fd96b3cdffd..f0f3bec0e17 100644\n--- a/git-curl-compat.h\n+++ b/git-curl-compat.h\n@@ -74,6 +74,13 @@\n #define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1\n #endif\n \n+/**\n+ * CURLOPT_UNIX_SOCKET_PATH was added in 7.40.0, released in January 2015.\n+ */\n+#if LIBCURL_VERSION_NUM >= 0x074000\n+#define GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH 1\n+#endif\n+\n /**\n  * CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015.\n  *\ndiff --git a/http.c b/http.c\nindex e73b136e589..8cfdcaeac82 100644\n--- a/http.c\n+++ b/http.c\n@@ -79,6 +79,9 @@ static const char *http_proxy_ssl_ca_info;\n static struct credential proxy_cert_auth = CREDENTIAL_INIT;\n static int proxy_ssl_cert_password_required;\n \n+#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n+static const char *curl_unix_socket_path;\n+#endif\n static struct {\n \tconst char *name;\n \tlong curlauth_param;\n@@ -455,6 +458,20 @@ static int http_options(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(\"http.unixsocket\", var)) {\n+#ifdef GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH\n+#ifndef NO_UNIX_SOCKETS\n+\t\treturn git_config_string(&curl_unix_socket_path, var, value);\n+#else\n+\t\twarning(_(\"Unix socket support unavailable in this build of Git\"));\n+\t\treturn 0;\n+#endif\n+#else\n+\t\twarning(_(\"Unix socket support is not supported with cURL < 7.40.0\"));\n+\t\treturn 0;\n+#endif\n+\t}\n+\n \tif (!strcmp(\"http.cookiefile\", var))\n \t\treturn git_config_pathname(&curl_cookie_file, var, value);\n \tif (!strcmp(\"http.savecookies\", var)) {\n@@ -1203,6 +1220,12 @@ static CURL *get_curl_handle(void)\n \t}\n \tinit_curl_proxy_auth(result);\n \n+#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n+\tif (curl_unix_socket_path) {\n+\t\tcurl_easy_setopt(result, CURLOPT_UNIX_SOCKET_PATH, curl_unix_socket_path);\n+\t}\n+#endif\n+\n \tset_curl_keepalive(result);\n \n \treturn result;\ndiff --git a/t/t5565-http-unix-domain-socket.sh b/t/t5565-http-unix-domain-socket.sh\nnew file mode 100755\nindex 00000000000..4ebcdfaa515\n--- /dev/null\n+++ b/t/t5565-http-unix-domain-socket.sh\n@@ -0,0 +1,80 @@\n+#!/bin/sh\n+\n+test_description=\"test fetching through http via unix domain socket\"\n+\n+. ./test-lib.sh\n+. \"$TEST_DIRECTORY\"/lib-httpd.sh\n+\n+test -z \"$NO_UNIX_SOCKETS\" || {\n+\tskip_all='skipping http-unix-socket tests, unix sockets not available'\n+\ttest_done\n+}\n+\n+UDS_TO_TCP_FIFO=uds_to_tcp\n+TCP_TO_UDS_FIFO=tcp_to_uds\n+UDS_PID=\n+TCP_PID=\n+UDS_SOCKET=\"$(pwd)/uds.sock\"\n+UNRESOLVABLE_ENDPOINT=http://localhost:4242\n+\n+start_proxy_unix_to_tcp() {\n+    local socket_path=\"$UDS_SOCKET\"\n+    local host=127.0.0.1\n+    local port=$LIB_HTTPD_PORT\n+\n+    rm -f \"$UDS_TO_TCP_FIFO\"\n+    rm -f \"$TCP_TO_UDS_FIFO\"\n+    rm -f \"$socket_path\"\n+    mkfifo \"$UDS_TO_TCP_FIFO\"\n+    mkfifo \"$TCP_TO_UDS_FIFO\"\n+    nc -klU \"$socket_path\" <tcp_to_uds >uds_to_tcp &\n+    UDS_PID=$!\n+\n+    nc \"$host\" \"$port\" >tcp_to_uds <uds_to_tcp &\n+    TCP_PID=$!\n+\n+    test_atexit 'stop_proxy_unix_to_tcp'\n+}\n+\n+stop_proxy_unix_to_tcp() {\n+    kill \"$UDS_PID\"\n+    kill \"$TCP_PID\"\n+    rm -f \"$UDS_TO_TCP_FIFO\"\n+    rm -f \"$TCP_TO_UDS_FIFO\"\n+}\n+\n+start_httpd\n+start_proxy_unix_to_tcp\n+\n+test_expect_success 'setup repository' '\n+\ttest_commit foo &&\n+\tgit init --bare \"$HTTPD_DOCUMENT_ROOT_PATH/repo.git\" &&\n+\tgit push --mirror \"$HTTPD_DOCUMENT_ROOT_PATH/repo.git\"\n+'\n+\n+# sanity check that we can't clone normally\n+test_expect_success 'cloning without UDS fails' '\n+    test_must_fail git clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n+'\n+\n+test_expect_success 'cloning with UDS succeeds' '\n+    test_when_finished \"rm -rf clone\" &&\n+\ttest_config_global http.unixsocket \"$UDS_SOCKET\" &&\n+\tgit clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n+'\n+\n+test_expect_success 'cloning with a non-existent http proxy fails' '\n+    git clone $HTTPD_URL/smart/repo.git clone &&\n+    rm -rf clone &&\n+    test_config_global http.proxy 127.0.0.1:0 &&\n+    test_must_fail git clone $HTTPD_URL/smart/repo.git clone\n+'\n+\n+test_expect_success 'UDS socket takes precedence over http proxy' '\n+    test_when_finished \"rm -rf clone\" &&\n+    test_config_global http.proxy 127.0.0.1:0 &&\n+    test_config_global http.unixsocket \"$UDS_SOCKET\" &&\n+    git clone $HTTPD_URL/smart/repo.git clone\n+'\n+\n+test_done\n\nbase-commit: 3e0d3cd5c7def4808247caf168e17f2bbf47892b\n-- \ngitgitgadget\n"},{"id":"489111","messageId":"20240221220945.M686016@dcvr","threadId":"60972","inReplyTo":"pull.1681.git.git.1708506863243.gitgitgadget@gmail.com","subject":"Re: [PATCH] Add unix domain socket support to HTTP transport.","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2024-02-21T22:09:45Z","receivedAt":"2024-02-21T22:18:30Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Leslie Cheng via GitGitGadget <gitgitgadget@gmail.com> wrote:\n\n> Subject: Re: [PATCH] Add unix domain socket support to HTTP transport.\n\nNo need for trailing `.' in commit message titles\n\n<snip>\n\n> @@ -455,6 +458,20 @@ static int http_options(const char *var, const char *value,\n>  \t\treturn 0;\n>  \t}\n>  \n> +\tif (!strcmp(\"http.unixsocket\", var)) {\n> +#ifdef GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH\n> +#ifndef NO_UNIX_SOCKETS\n> +\t\treturn git_config_string(&curl_unix_socket_path, var, value);\n> +#else\n> +\t\twarning(_(\"Unix socket support unavailable in this build of Git\"));\n> +\t\treturn 0;\n> +#endif\n> +#else\n> +\t\twarning(_(\"Unix socket support is not supported with cURL < 7.40.0\"));\n> +\t\treturn 0;\n> +#endif\n> +\t}\n\nPersonally, I'd hoist the #ifdef part into a standalone function\nsince I find mixing CPP and C conditionals confusing.\n\ndisclaimer: I'm an easily confused person and don't usually\nprogram in C, though.\n\n<snip>\n\n> --- /dev/null\n> +++ b/t/t5565-http-unix-domain-socket.sh\n\n<snip>\n\n> +    nc -klU \"$socket_path\" <tcp_to_uds >uds_to_tcp &\n> +    UDS_PID=$!\n> +\n> +    nc \"$host\" \"$port\" >tcp_to_uds <uds_to_tcp &\n\n`nc' isn't widely installed, its supported flags vary between\nimplementations, and our test suite doesn't currently use it.\nI suggest either using a small bit of Perl or writing a t/helper\nprogram to do its job.\n\nFinally, hard tabs should be used for indentation throughout.\n\nI'll wait on others to comment since I haven't looked at git\nhacking in a while.\n\nAnyways, I think this feature could be useful for me, too :>\nThanks.\n"},{"id":"489119","messageId":"5a857e76-659d-4d94-ae54-f5c22c9917c6@gmail.com","threadId":"60972","inReplyTo":"20240221220945.M686016@dcvr","subject":"Re: [PATCH] Add unix domain socket support to HTTP transport.","fromName":"Leslie Cheng","fromEmail":"leslie.cheng5@gmail.com","sentAt":"2024-02-22T03:04:38Z","receivedAt":"2024-02-22T03:04:40Z","isPatch":true,"sender":{"key":"leslie.cheng5@gmail.com","avatar":null},"body":"> No need for trailing `.' in commit message titles\n\nWill fix in the next patch, sorry!\n\n\n> Personally, I'd hoist the #ifdef part into a standalone function\n> since I find mixing CPP and C conditionals confusing.\n> \n> disclaimer: I'm an easily confused person and don't usually\n> program in C, though.\n\nI considered extracting it out, but the other conditionals in this \nfunction follow a similar pattern so I didn't want to change it. \nHowever, my use here is also the first time there's both an #ifdef and \nnested #ifndef, which I agree makes it a bit confusing to grok.\n\nI'm open to changing it, but I'll let it sit and marinate for a bit.\n\n\n> `nc' isn't widely installed, its supported flags vary between\n> implementations, and our test suite doesn't currently use it.\n> I suggest either using a small bit of Perl or writing a t/helper\n> program to do its job.\n> \n> Finally, hard tabs should be used for indentation throughout.\n> \n> I'll wait on others to comment since I haven't looked at git\n> hacking in a while.\n> \n> Anyways, I think this feature could be useful for me, too :>\n> Thanks.\n\nGood catch, I'll fix in the next patch. I've subbed `nc` out for a \nsimple Perl script to pipe back and forth, just making sure CI is happy \nabout this before submitting.\n"},{"id":"489194","messageId":"pull.1681.v2.git.git.1708653536115.gitgitgadget@gmail.com","threadId":"60972","inReplyTo":"pull.1681.git.git.1708506863243.gitgitgadget@gmail.com","subject":"[PATCH v2] Add unix domain socket support to HTTP transport","fromName":"Leslie Cheng via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-02-23T01:58:55Z","receivedAt":"2024-02-23T01:58:59Z","isPatch":true,"sender":{"key":"leslie.cheng5@gmail.com","avatar":null},"body":"From: Leslie Cheng <leslie.cheng5@gmail.com>\n\nThis changeset introduces an `http.unixSocket` option so that users can\nproxy their git over HTTP remotes to a unix domain socket. In terms of\nwhy, since UDS are local and git already has a local protocol: some\ncorporate environments use a UDS to proxy requests to internal resources\n(ie. source control), so this change would support those use-cases. This\nproxy can occasionally be necessary to attach MFA tokens or client\ncertificates for CLI tools.\n\nThe implementation leverages `--unix-socket` option [0] via the\n`CURLOPT_UNIX_SOCKET_PATH` flag available with libcurl [1].\n\n`GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH` and `NO_UNIX_SOCKETS` were kept\nseparate so that we can spit out better error messages for users if git\nwas compiled with `NO_UNIX_SOCKETS`.\n\n[0] https://curl.se/docs/manpage.html#--unix-socket\n[1] https://curl.se/libcurl/c/CURLOPT_UNIX_SOCKET_PATH.html\n\nSigned-off-by: Leslie Cheng <leslie@lc.fyi>\n---\n    Add unix domain socket support to HTTP transport\n    \n    Changes since v1:\n    \n     * Updated test to use Perl instead of nc to proxy between UDS and TCP\n       socket; I chose not to split this out into a library since its use is\n       hyper-specific and has a dependency on lib-httpd.sh\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1681%2Flcfyi%2Flcfyi%2Fadd-unix-socket-support-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1681/lcfyi/lcfyi/add-unix-socket-support-v2\nPull-Request: https://github.com/git/git/pull/1681\n\nRange-diff vs v1:\n\n 1:  3e531632329 ! 1:  2af5cc8089b Add unix domain socket support to HTTP transport.\n     @@ Metadata\n      Author: Leslie Cheng <leslie.cheng5@gmail.com>\n      \n       ## Commit message ##\n     -    Add unix domain socket support to HTTP transport.\n     +    Add unix domain socket support to HTTP transport\n      \n          This changeset introduces an `http.unixSocket` option so that users can\n          proxy their git over HTTP remotes to a unix domain socket. In terms of\n     @@ t/t5565-http-unix-domain-socket.sh (new)\n      +\ttest_done\n      +}\n      +\n     -+UDS_TO_TCP_FIFO=uds_to_tcp\n     -+TCP_TO_UDS_FIFO=tcp_to_uds\n     -+UDS_PID=\n     -+TCP_PID=\n     ++if ! test_have_prereq PERL\n     ++then\n     ++\tskip_all='skipping http-unix-socket tests; perl not available'\n     ++\ttest_done\n     ++fi\n     ++\n     ++SOCKET_PROXY_PIDFILE=\"$(pwd)/proxy.pid\"\n      +UDS_SOCKET=\"$(pwd)/uds.sock\"\n     -+UNRESOLVABLE_ENDPOINT=http://localhost:4242\n     ++UNRESOLVABLE_ENDPOINT=http://unresolved\n      +\n      +start_proxy_unix_to_tcp() {\n     -+    local socket_path=\"$UDS_SOCKET\"\n     -+    local host=127.0.0.1\n     -+    local port=$LIB_HTTPD_PORT\n     -+\n     -+    rm -f \"$UDS_TO_TCP_FIFO\"\n     -+    rm -f \"$TCP_TO_UDS_FIFO\"\n     -+    rm -f \"$socket_path\"\n     -+    mkfifo \"$UDS_TO_TCP_FIFO\"\n     -+    mkfifo \"$TCP_TO_UDS_FIFO\"\n     -+    nc -klU \"$socket_path\" <tcp_to_uds >uds_to_tcp &\n     -+    UDS_PID=$!\n     -+\n     -+    nc \"$host\" \"$port\" >tcp_to_uds <uds_to_tcp &\n     -+    TCP_PID=$!\n     -+\n     -+    test_atexit 'stop_proxy_unix_to_tcp'\n     ++\ttest_atexit 'stop_proxy_unix_to_tcp'\n     ++\n     ++\tperl -Mstrict -MIO::Select -MIO::Socket::INET -MIO::Socket::UNIX -e '\n     ++\t\tmy $uds_path = $ARGV[0];\n     ++\t\tmy $host = $ARGV[1];\n     ++\t\tmy $port = $ARGV[2];\n     ++\t\tmy $pidfile = $ARGV[3];\n     ++\n     ++\t\topen(my $fh, \">\", $pidfile) or die \"failed to create pidfile\";\n     ++\t\tprint $fh \"$$\";\n     ++\t\tclose($fh);\n     ++\n     ++\t\tmy $uds = IO::Socket::UNIX->new(\n     ++\t\t\tLocal => $uds_path,\n     ++\t\t\tType => SOCK_STREAM,\n     ++\t\t\tListen => 5,\n     ++\t\t) or die \"failed to create unix domain socket\";\n     ++\n     ++\t\twhile (my $conn = $uds->accept()) {\n     ++\t\t\tmy $tcp_client = IO::Socket::INET->new(\n     ++\t\t\t\tPeerAddr => $host,\n     ++\t\t\t\tPeerPort => $port,\n     ++\t\t\t\tProto => \"tcp\",\n     ++\t\t\t) or die \"failed to create TCP socket\";\n     ++\n     ++\t\t\tmy $sel = IO::Select->new($conn, $tcp_client);\n     ++\n     ++\t\t\twhile (my @ready = $sel->can_read(10)) {\n     ++\t\t\t\tforeach my $socket (@ready) {\n     ++\t\t\t\t\tmy $other = ($socket == $conn) ? $tcp_client : $conn;\n     ++\t\t\t\t\tmy $data;\n     ++\t\t\t\t\tmy $bytes = $socket->sysread($data, 4096);\n     ++\n     ++\t\t\t\t\tif ($bytes) {\n     ++\t\t\t\t\t\t$other->syswrite($data, $bytes);\n     ++\t\t\t\t\t} else {\n     ++\t\t\t\t\t\t$socket->close();\n     ++\t\t\t\t\t}\n     ++\t\t\t\t}\n     ++\t\t\t}\n     ++\t\t}\n     ++\t' \"$UDS_SOCKET\" \"127.0.0.1\" \"$LIB_HTTPD_PORT\" \"$SOCKET_PROXY_PIDFILE\" &\n     ++\tSOCKET_PROXY_PID=$!\n      +}\n      +\n      +stop_proxy_unix_to_tcp() {\n     -+    kill \"$UDS_PID\"\n     -+    kill \"$TCP_PID\"\n     -+    rm -f \"$UDS_TO_TCP_FIFO\"\n     -+    rm -f \"$TCP_TO_UDS_FIFO\"\n     ++\tkill -9 \"$(cat \"$SOCKET_PROXY_PIDFILE\")\"\n     ++\trm -f \"$SOCKET_PROXY_PIDFILE\"\n     ++\trm -f \"$UDS_SOCKET\"\n      +}\n      +\n      +start_httpd\n     @@ t/t5565-http-unix-domain-socket.sh (new)\n      +\n      +# sanity check that we can't clone normally\n      +test_expect_success 'cloning without UDS fails' '\n     -+    test_must_fail git clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n     ++\ttest_must_fail git clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n      +'\n      +\n      +test_expect_success 'cloning with UDS succeeds' '\n     -+    test_when_finished \"rm -rf clone\" &&\n     ++\ttest_when_finished \"rm -rf clone\" &&\n      +\ttest_config_global http.unixsocket \"$UDS_SOCKET\" &&\n      +\tgit clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n      +'\n      +\n      +test_expect_success 'cloning with a non-existent http proxy fails' '\n     -+    git clone $HTTPD_URL/smart/repo.git clone &&\n     -+    rm -rf clone &&\n     -+    test_config_global http.proxy 127.0.0.1:0 &&\n     -+    test_must_fail git clone $HTTPD_URL/smart/repo.git clone\n     ++\tgit clone $HTTPD_URL/smart/repo.git clone &&\n     ++\trm -rf clone &&\n     ++\ttest_config_global http.proxy 127.0.0.1:0 &&\n     ++\ttest_must_fail git clone $HTTPD_URL/smart/repo.git clone\n      +'\n      +\n      +test_expect_success 'UDS socket takes precedence over http proxy' '\n     -+    test_when_finished \"rm -rf clone\" &&\n     -+    test_config_global http.proxy 127.0.0.1:0 &&\n     -+    test_config_global http.unixsocket \"$UDS_SOCKET\" &&\n     -+    git clone $HTTPD_URL/smart/repo.git clone\n     ++\ttest_when_finished \"rm -rf clone\" &&\n     ++\ttest_config_global http.proxy 127.0.0.1:0 &&\n     ++\ttest_config_global http.unixsocket \"$UDS_SOCKET\" &&\n     ++\tgit clone $HTTPD_URL/smart/repo.git clone\n      +'\n      +\n      +test_done\n\n\n Documentation/config/http.txt      |   5 ++\n git-curl-compat.h                  |   7 ++\n http.c                             |  23 ++++++\n t/t5565-http-unix-domain-socket.sh | 109 +++++++++++++++++++++++++++++\n 4 files changed, 144 insertions(+)\n create mode 100755 t/t5565-http-unix-domain-socket.sh\n\ndiff --git a/Documentation/config/http.txt b/Documentation/config/http.txt\nindex 2d4e0c9b869..bf48cbd599a 100644\n--- a/Documentation/config/http.txt\n+++ b/Documentation/config/http.txt\n@@ -277,6 +277,11 @@ http.followRedirects::\n \tthe base for the follow-up requests, this is generally\n \tsufficient. The default is `initial`.\n \n+http.unixSocket::\n+\tConnect through this Unix domain socket via HTTP, instead of using the\n+\tnetwork. If set, this config takes precendence over `http.proxy` and\n+\tis incompatible with the proxy options (see `curl(1)`).\n+\n http.<url>.*::\n \tAny of the http.* options above can be applied selectively to some URLs.\n \tFor a config key to match a URL, each element of the config key is\ndiff --git a/git-curl-compat.h b/git-curl-compat.h\nindex fd96b3cdffd..f0f3bec0e17 100644\n--- a/git-curl-compat.h\n+++ b/git-curl-compat.h\n@@ -74,6 +74,13 @@\n #define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1\n #endif\n \n+/**\n+ * CURLOPT_UNIX_SOCKET_PATH was added in 7.40.0, released in January 2015.\n+ */\n+#if LIBCURL_VERSION_NUM >= 0x074000\n+#define GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH 1\n+#endif\n+\n /**\n  * CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015.\n  *\ndiff --git a/http.c b/http.c\nindex e73b136e589..8cfdcaeac82 100644\n--- a/http.c\n+++ b/http.c\n@@ -79,6 +79,9 @@ static const char *http_proxy_ssl_ca_info;\n static struct credential proxy_cert_auth = CREDENTIAL_INIT;\n static int proxy_ssl_cert_password_required;\n \n+#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n+static const char *curl_unix_socket_path;\n+#endif\n static struct {\n \tconst char *name;\n \tlong curlauth_param;\n@@ -455,6 +458,20 @@ static int http_options(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(\"http.unixsocket\", var)) {\n+#ifdef GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH\n+#ifndef NO_UNIX_SOCKETS\n+\t\treturn git_config_string(&curl_unix_socket_path, var, value);\n+#else\n+\t\twarning(_(\"Unix socket support unavailable in this build of Git\"));\n+\t\treturn 0;\n+#endif\n+#else\n+\t\twarning(_(\"Unix socket support is not supported with cURL < 7.40.0\"));\n+\t\treturn 0;\n+#endif\n+\t}\n+\n \tif (!strcmp(\"http.cookiefile\", var))\n \t\treturn git_config_pathname(&curl_cookie_file, var, value);\n \tif (!strcmp(\"http.savecookies\", var)) {\n@@ -1203,6 +1220,12 @@ static CURL *get_curl_handle(void)\n \t}\n \tinit_curl_proxy_auth(result);\n \n+#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n+\tif (curl_unix_socket_path) {\n+\t\tcurl_easy_setopt(result, CURLOPT_UNIX_SOCKET_PATH, curl_unix_socket_path);\n+\t}\n+#endif\n+\n \tset_curl_keepalive(result);\n \n \treturn result;\ndiff --git a/t/t5565-http-unix-domain-socket.sh b/t/t5565-http-unix-domain-socket.sh\nnew file mode 100755\nindex 00000000000..2f9c53ab14f\n--- /dev/null\n+++ b/t/t5565-http-unix-domain-socket.sh\n@@ -0,0 +1,109 @@\n+#!/bin/sh\n+\n+test_description=\"test fetching through http via unix domain socket\"\n+\n+. ./test-lib.sh\n+. \"$TEST_DIRECTORY\"/lib-httpd.sh\n+\n+test -z \"$NO_UNIX_SOCKETS\" || {\n+\tskip_all='skipping http-unix-socket tests, unix sockets not available'\n+\ttest_done\n+}\n+\n+if ! test_have_prereq PERL\n+then\n+\tskip_all='skipping http-unix-socket tests; perl not available'\n+\ttest_done\n+fi\n+\n+SOCKET_PROXY_PIDFILE=\"$(pwd)/proxy.pid\"\n+UDS_SOCKET=\"$(pwd)/uds.sock\"\n+UNRESOLVABLE_ENDPOINT=http://unresolved\n+\n+start_proxy_unix_to_tcp() {\n+\ttest_atexit 'stop_proxy_unix_to_tcp'\n+\n+\tperl -Mstrict -MIO::Select -MIO::Socket::INET -MIO::Socket::UNIX -e '\n+\t\tmy $uds_path = $ARGV[0];\n+\t\tmy $host = $ARGV[1];\n+\t\tmy $port = $ARGV[2];\n+\t\tmy $pidfile = $ARGV[3];\n+\n+\t\topen(my $fh, \">\", $pidfile) or die \"failed to create pidfile\";\n+\t\tprint $fh \"$$\";\n+\t\tclose($fh);\n+\n+\t\tmy $uds = IO::Socket::UNIX->new(\n+\t\t\tLocal => $uds_path,\n+\t\t\tType => SOCK_STREAM,\n+\t\t\tListen => 5,\n+\t\t) or die \"failed to create unix domain socket\";\n+\n+\t\twhile (my $conn = $uds->accept()) {\n+\t\t\tmy $tcp_client = IO::Socket::INET->new(\n+\t\t\t\tPeerAddr => $host,\n+\t\t\t\tPeerPort => $port,\n+\t\t\t\tProto => \"tcp\",\n+\t\t\t) or die \"failed to create TCP socket\";\n+\n+\t\t\tmy $sel = IO::Select->new($conn, $tcp_client);\n+\n+\t\t\twhile (my @ready = $sel->can_read(10)) {\n+\t\t\t\tforeach my $socket (@ready) {\n+\t\t\t\t\tmy $other = ($socket == $conn) ? $tcp_client : $conn;\n+\t\t\t\t\tmy $data;\n+\t\t\t\t\tmy $bytes = $socket->sysread($data, 4096);\n+\n+\t\t\t\t\tif ($bytes) {\n+\t\t\t\t\t\t$other->syswrite($data, $bytes);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\t$socket->close();\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t' \"$UDS_SOCKET\" \"127.0.0.1\" \"$LIB_HTTPD_PORT\" \"$SOCKET_PROXY_PIDFILE\" &\n+\tSOCKET_PROXY_PID=$!\n+}\n+\n+stop_proxy_unix_to_tcp() {\n+\tkill -9 \"$(cat \"$SOCKET_PROXY_PIDFILE\")\"\n+\trm -f \"$SOCKET_PROXY_PIDFILE\"\n+\trm -f \"$UDS_SOCKET\"\n+}\n+\n+start_httpd\n+start_proxy_unix_to_tcp\n+\n+test_expect_success 'setup repository' '\n+\ttest_commit foo &&\n+\tgit init --bare \"$HTTPD_DOCUMENT_ROOT_PATH/repo.git\" &&\n+\tgit push --mirror \"$HTTPD_DOCUMENT_ROOT_PATH/repo.git\"\n+'\n+\n+# sanity check that we can't clone normally\n+test_expect_success 'cloning without UDS fails' '\n+\ttest_must_fail git clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n+'\n+\n+test_expect_success 'cloning with UDS succeeds' '\n+\ttest_when_finished \"rm -rf clone\" &&\n+\ttest_config_global http.unixsocket \"$UDS_SOCKET\" &&\n+\tgit clone \"$UNRESOLVABLE_ENDPOINT/smart/repo.git\" clone\n+'\n+\n+test_expect_success 'cloning with a non-existent http proxy fails' '\n+\tgit clone $HTTPD_URL/smart/repo.git clone &&\n+\trm -rf clone &&\n+\ttest_config_global http.proxy 127.0.0.1:0 &&\n+\ttest_must_fail git clone $HTTPD_URL/smart/repo.git clone\n+'\n+\n+test_expect_success 'UDS socket takes precedence over http proxy' '\n+\ttest_when_finished \"rm -rf clone\" &&\n+\ttest_config_global http.proxy 127.0.0.1:0 &&\n+\ttest_config_global http.unixsocket \"$UDS_SOCKET\" &&\n+\tgit clone $HTTPD_URL/smart/repo.git clone\n+'\n+\n+test_done\n\nbase-commit: 3e0d3cd5c7def4808247caf168e17f2bbf47892b\n-- \ngitgitgadget\n"},{"id":"489232","messageId":"xmqqzfvrzic9.fsf@gitster.g","threadId":"60972","inReplyTo":"pull.1681.v2.git.git.1708653536115.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] Add unix domain socket support to HTTP transport","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-02-23T08:37:58Z","receivedAt":"2024-02-23T08:38:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Leslie Cheng via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> Subject: Re: [PATCH v2] Add unix domain socket support to HTTP transport\n\nPerhaps\n\n\tSubject: [PATCH] http: enable proxying via unix-domain socket\n\nto follow the usual \"<area>: <description>\" format?\n\n> From: Leslie Cheng <leslie.cheng5@gmail.com>\n>\n> This changeset introduces an `http.unixSocket` option so that users can\n\n\"This changeset introduces\" -> \"Introduce\".  There may be other\ngotchas that might use help from Documentation/SubmittingPatches,\nbut I didn't read too carefully.\n\nBesides, it is a single patch, not a set of changes ;-).\n\n`http.unixSocket` is a configuration variable.  It may be confusing\nto use the word \"option\".  Speaking of options, shouldn't there be a\ncommand line option that overrides the configured value?\n\nWe should honor the usual http.<url>.VARIABLE convention where\nhttp.<url>.VARIABLE that is destination-specific overrides a more\ngeneric http.VARIABLE configuration variable.\n\n> proxy their git over HTTP remotes to a unix domain socket. In terms of\n> why, since UDS are local and git already has a local protocol: some\n> corporate environments use a UDS to proxy requests to internal resources\n> (ie. source control), so this change would support those use-cases. This\n\n\"ie.\" -> \"i.e.,\"?\n\n> proxy can occasionally be necessary to attach MFA tokens or client\n> certificates for CLI tools.\n>\n> The implementation leverages `--unix-socket` option [0] via the\n> `CURLOPT_UNIX_SOCKET_PATH` flag available with libcurl [1].\n\nThere is a feature in libcURL library, that is enabled by setting\nthe CURLOPT_UNIX_SOCKET_PATH option via the curl_easy_setopt() call,\nand their command line utility.  You do the same to implement this\nfeature.  But when you are not adding \"--unix-socket\" option to any\nof our commands, mention of that option name makes it more confusing\nthan necessary.\n\nThe usual way to compose a log message of this project is to\n\n - Give an observation on how the current system work in the present\n   tense (so no need to say \"Currently X is Y\", just \"X is Y\"), and\n   discuss what you perceive as a problem in it.\n\n - Propose a solution (optional---often, problem description\n   trivially leads to an obvious solution in reader's minds).\n\n - Give commands to the codebase to \"become like so\".\n\nin this order.\n\nHow about following that convention, perhaps like:\n\n    In some corporate environments, the proxy server listens to a\n    local unix domain socket for requests, instead of listening to a\n    network port.  Even though we have http.proxy (and more\n    destination specific http.<url>.proxy) configuration variables\n    to specify the network address/port of a proxy, that would not\n    help if your proxy does not listen to the network.\n\n    Introduce an `http.unixSocket` (and `http.<url>.unixSocket`)\n    configuration variables that specify the path to a unix domain\n    socket for such a proxy.  Recent versions of libcURL library\n    added CURLOPT_UNIX_SOCKET_PATH to support \"curl --unix-socket\n    <path>\"---use the same mechanism to implement it.\n\n> `GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH` and `NO_UNIX_SOCKETS` were kept\n> separate so that we can spit out better error messages for users if git\n> was compiled with `NO_UNIX_SOCKETS`.\n\nUnlike NO_UNIX_SOCKETS, GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH is\nentirely internal to your implementation and not surfaced to neither\nthe end-users or the binary packagers.  Because of that, I suspect\nthat any description that has to use that name probably falls on the\nother side of \"too much implementation details\" to be useful to help\nfuture developers..\n\nBesides, I suspect that GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH might\nnot be the optimum approach.  See below.\n\n> diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt\n> index 2d4e0c9b869..bf48cbd599a 100644\n> --- a/Documentation/config/http.txt\n> +++ b/Documentation/config/http.txt\n> @@ -277,6 +277,11 @@ http.followRedirects::\n>  \tthe base for the follow-up requests, this is generally\n>  \tsufficient. The default is `initial`.\n>  \n> +http.unixSocket::\n> +\tConnect through this Unix domain socket via HTTP, instead of using the\n> +\tnetwork. If set, this config takes precendence over `http.proxy` and\n> +\tis incompatible with the proxy options (see `curl(1)`).\n\nTalking about precedence between this and http.proxy is good thing,\nbut one very important piece of information is missing.  What value\ndoes it take?\n\n\tThe absolute path of a unix-domain socket to pass the HTTP\n\ttraffic over, instead of using the network.\n\nor something, perhaps?\n\n> diff --git a/git-curl-compat.h b/git-curl-compat.h\n> index fd96b3cdffd..f0f3bec0e17 100644\n> --- a/git-curl-compat.h\n> +++ b/git-curl-compat.h\n> @@ -74,6 +74,13 @@\n>  #define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1\n>  #endif\n>  \n> +/**\n> + * CURLOPT_UNIX_SOCKET_PATH was added in 7.40.0, released in January 2015.\n> + */\n> +#if LIBCURL_VERSION_NUM >= 0x074000\n> +#define GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH 1\n> +#endif\n\nThe \"HAVE\" part in GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH is a\nstatement of a fact.  If the version of cURL library we have is\ncertain value, we have it.  OK.\n\n> diff --git a/http.c b/http.c\n> index e73b136e589..8cfdcaeac82 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -79,6 +79,9 @@ static const char *http_proxy_ssl_ca_info;\n>  static struct credential proxy_cert_auth = CREDENTIAL_INIT;\n>  static int proxy_ssl_cert_password_required;\n\nIt might make the code easier to follow if you did:\n\n\t#if !defined(NO_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n\t#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH)\n        #define USE_CURLOPT_UNIX_SOCKET_PATH\n\t#endif\n\t#endif\n        \nThe points are\n\n (1) the users can decline to use CURLOPT_UNIX_SOCKET_PATH while\n     still using unix domain socket for other purposes, and\n\n (2) you do not have to care if you HAVE it or not most of time;\n     what matters more often is if the user told you to USE it.\n\nHmm?\n\n> +#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n> +static const char *curl_unix_socket_path;\n> +#endif\n\nThe guard here would become \"#ifdef USE_CURLOPT_UNIX_SOCKET_PATH\" if\nwe wanted this to be conditional, but I think it is easier to make\nthe variable unconditionally available; see below.\n\n> @@ -455,6 +458,20 @@ static int http_options(const char *var, const char *value,\n>  \t\treturn 0;\n>  \t}\n>  \n> +\tif (!strcmp(\"http.unixsocket\", var)) {\n> +#ifdef GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH\n> +#ifndef NO_UNIX_SOCKETS\n> +\t\treturn git_config_string(&curl_unix_socket_path, var, value);\n> +#else\n> +\t\twarning(_(\"Unix socket support unavailable in this build of Git\"));\n> +\t\treturn 0;\n> +#endif\n> +#else\n> +\t\twarning(_(\"Unix socket support is not supported with cURL < 7.40.0\"));\n> +\t\treturn 0;\n> +#endif\n> +\t}\n\nIn general, it is inadvisable to issue a warning in the codepath\nthat parses configuration variables, as the values we read may not\nbe necessarily used.  We could instead accept the given path into a\nvariable unconditionally, and complain only before it gets used,\nnear the call to curl_easy_setopt().\n\n>  \tif (!strcmp(\"http.cookiefile\", var))\n>  \t\treturn git_config_pathname(&curl_cookie_file, var, value);\n>  \tif (!strcmp(\"http.savecookies\", var)) {\n> @@ -1203,6 +1220,12 @@ static CURL *get_curl_handle(void)\n>  \t}\n>  \tinit_curl_proxy_auth(result);\n>  \n> +#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n> +\tif (curl_unix_socket_path) {\n> +\t\tcurl_easy_setopt(result, CURLOPT_UNIX_SOCKET_PATH, curl_unix_socket_path);\n> +\t}\n> +#endif\n\nHere, the guard may become more like\n\n\t\tif (curl_unix_socket_path) {\n\t#ifdef USE_CURLOPT_UNIX_SOCKET_PATH\n\t\t\tcurl_easy_setopt(...);\n\t#elif defined(NO_CURLOPT_UNIX_SOCKET_PATH) || defined(NO_UNIX_SOCKETS)\n\t\t\twarning(_(\"this build disables the unix-domain-socket feature\"));\n\t#elif\n\t\t\twarning(_(\"your cURL library is too old\"));\n\t#endif\n\t\t}\n"},{"id":"489239","messageId":"xmqq5xyfyyn0.fsf@gitster.g","threadId":"60972","inReplyTo":"xmqqzfvrzic9.fsf@gitster.g","subject":"Re: [PATCH v2] Add unix domain socket support to HTTP transport","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-02-23T15:43:31Z","receivedAt":"2024-02-23T15:43:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> \"Leslie Cheng via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n>> Subject: Re: [PATCH v2] Add unix domain socket support to HTTP transport\n>\n> Perhaps\n>\n> \tSubject: [PATCH] http: enable proxying via unix-domain socket\n>\n> to follow the usual \"<area>: <description>\" format?\n>\n>> From: Leslie Cheng <leslie.cheng5@gmail.com>\n>>\n>> This changeset introduces an `http.unixSocket` option so that users can\n>\n> \"This changeset introduces\" -> \"Introduce\".  There may be other\n> gotchas that might use help from Documentation/SubmittingPatches,\n> but I didn't read too carefully.\n>\n> Besides, it is a single patch, not a set of changes ;-).\n>\n> `http.unixSocket` is a configuration variable.  It may be confusing\n> to use the word \"option\".  Speaking of options, shouldn't there be a\n> command line option that overrides the configured value?\n>\n> We should honor the usual http.<url>.VARIABLE convention where\n> http.<url>.VARIABLE that is destination-specific overrides a more\n> generic http.VARIABLE configuration variable.\n\nClarification.  I know the above is automatically achieved, given\nthe way we have laid urlmatch foundation to allow easy parsing for\nconfiguration variables structured this way.  I did not mean that\nyou'd need to do anything special; rather, I meant that we should\nadvertise that we do in the commit log message.\n\n"},{"id":"489260","messageId":"4dfca119-3210-4574-998b-0bee53e61464@gmail.com","threadId":"60972","inReplyTo":"xmqq5xyfyyn0.fsf@gitster.g","subject":"Re: [PATCH v2] Add unix domain socket support to HTTP transport","fromName":"Leslie Cheng","fromEmail":"leslie.cheng5@gmail.com","sentAt":"2024-02-23T22:24:33Z","receivedAt":"2024-02-23T22:24:35Z","isPatch":true,"sender":{"key":"leslie.cheng5@gmail.com","avatar":null},"body":"On 2024-02-23 12:37 a.m., Junio C Hamano wrote:\n> How about following that convention, perhaps like:\n>\n>     In some corporate environments, the proxy server listens to a\n>     local unix domain socket for requests, instead of listening to a\n>     network port.  Even though we have http.proxy (and more\n>     destination specific http.<url>.proxy) configuration variables\n>     to specify the network address/port of a proxy, that would not\n>     help if your proxy does not listen to the network.\n>\n>     Introduce an `http.unixSocket` (and `http.<url>.unixSocket`)\n>     configuration variables that specify the path to a unix domain\n>     socket for such a proxy.  Recent versions of libcURL library\n>     added CURLOPT_UNIX_SOCKET_PATH to support \"curl --unix-socket\n>     <path>\"---use the same mechanism to implement it.\n\nThis is excellent, thanks for the guidance (and all the other\nsuggestions prior)! I'll update in the next patch.\n\n\n> Unlike NO_UNIX_SOCKETS, GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH is\n> entirely internal to your implementation and not surfaced to neither\n> the end-users or the binary packagers.  Because of that, I suspect\n> that any description that has to use that name probably falls on the\n> other side of \"too much implementation details\" to be useful to help\n> future developers..\n\nThat's reasonable, I figured it would fit as a cover letter detail but I\nagree it's not relevant as a commit message that lives in the history of\nthe project. I'll also update this in the next patch.\n\n\n> Talking about precedence between this and http.proxy is good thing,\n> but one very important piece of information is missing.  What value\n> does it take?\n>\n> \tThe absolute path of a unix-domain socket to pass the HTTP\n> \ttraffic over, instead of using the network.\n>\n> or something, perhaps?\n\nI like that wording, I'll update in the next patch.\n\n\n> It might make the code easier to follow if you did:\n>\n> \t#if !defined(NO_CURLOPT_UNIX_SOCKET_PATH) && !defined(NO_UNIX_SOCKETS)\n> \t#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH)\n>         #define USE_CURLOPT_UNIX_SOCKET_PATH\n> \t#endif\n> \t#endif\n>\n> The points are\n>\n>  (1) the users can decline to use CURLOPT_UNIX_SOCKET_PATH while\n>      still using unix domain socket for other purposes, and\n>\n>  (2) you do not have to care if you HAVE it or not most of time;\n>      what matters more often is if the user told you to USE it.\n>\n> Hmm?\n\nDo you think this functionality is worth adding another macro to\nconditionally include it in the build? It felt out-of-the-way enough\nthat we could just use the same `NO_UNIX_SOCKETS` macro to control for\nenvironments that don't support unix domain sockets.\n\n\n>> +#if defined(GIT_CURL_HAVE_CURLOPT_UNIX_SOCKET_PATH) &&\n!defined(NO_UNIX_SOCKETS)\n>> +static const char *curl_unix_socket_path;\n>> +#endif\n>\n> The guard here would become \"#ifdef USE_CURLOPT_UNIX_SOCKET_PATH\" if\n> we wanted this to be conditional, but I think it is easier to make\n> the variable unconditionally available; see below.\n\nAgreed in general, I was looking to other patterns for conditional\nvariables in file, e.g.\nhttps://github.com/git/git/blob/3c2a3fdc388747b9eaf4a4a4f2035c1c9ddb26d0/http.c#L66-L68\n\nBut, revisiting, this looks like an exception rather than the norm.\n\n\n> In general, it is inadvisable to issue a warning in the codepath\n> that parses configuration variables, as the values we read may not\n> be necessarily used.  We could instead accept the given path into a\n> variable unconditionally, and complain only before it gets used,\n> near the call to curl_easy_setopt().\n\nSimilar to above, I followed what was already done for certain\nconfiguration variables (e.g.\nhttps://github.com/git/git/blob/3c2a3fdc388747b9eaf4a4a4f2035c1c9ddb26d0/http.c#L485-L501),\nbut I agree with your feedback since this would result in constant warnings.\n\n\nTo summarize, I'll do the following in the next patch:\n - change the wording of the commit message\n - move the conditional variables and parsing to a check at\n`curl_easy_setopt()` time\n\nI'm still undecided on whether I should introduce another macro\nspecifically for this functionality, and I'd like to hear your thoughts\non why it might make sense.\n\n"}]}