Skip to content

Commit

Permalink
http: add custom hostname to IP address resolutions
Browse files Browse the repository at this point in the history
Libcurl has a CURLOPT_RESOLVE easy option that allows
the result of hostname resolution in the following
format to be passed:

	[+]HOST:PORT:ADDRESS[,ADDRESS]

This way, redirects and everything operating against the
HOST+PORT will use the provided ADDRESS(s).

The following format is also allowed to stop using
hostname resolutions that have already been passed:

	-HOST:PORT

See https://curl.se/libcurl/c/CURLOPT_RESOLVE.html for
more details.

Let's add a corresponding "http.curloptResolve" config
option that takes advantage of CURLOPT_RESOLVE.

Each value configured for the "http.curloptResolve" key
is passed "as is" to libcurl through CURLOPT_RESOLVE, so
it should be in one of the above 2 formats. This keeps
the implementation simple and makes us consistent with
libcurl's CURLOPT_RESOLVE, and with curl's corresponding
`--resolve` command line option.

The implementation uses CURLOPT_RESOLVE only in
get_active_slot() which is called by all the HTTP
request sending functions.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
chriscool authored and gitster committed May 16, 2022
1 parent 6cd33dc commit 511cfd3
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Documentation/config/http.txt
Expand Up @@ -98,6 +98,22 @@ http.version::
- HTTP/2
- HTTP/1.1

http.curloptResolve::
Hostname resolution information that will be used first by
libcurl when sending HTTP requests. This information should
be in one of the following formats:

- [+]HOST:PORT:ADDRESS[,ADDRESS]
- -HOST:PORT

+
The first format redirects all requests to the given `HOST:PORT`
to the provided `ADDRESS`(s). The second format clears all
previous config values for that `HOST:PORT` combination. To
allow easy overriding of all the settings inherited from the
system config, an empty value will reset all resolution
information to the empty list.

http.sslVersion::
The SSL version to use when negotiating an SSL connection, if you
want to force the default. The available and default version
Expand Down
18 changes: 18 additions & 0 deletions http.c
Expand Up @@ -128,6 +128,8 @@ static struct curl_slist *pragma_header;
static struct curl_slist *no_pragma_header;
static struct string_list extra_http_headers = STRING_LIST_INIT_DUP;

static struct curl_slist *host_resolutions;

static struct active_request_slot *active_queue_head;

static char *cached_accept_language;
Expand Down Expand Up @@ -393,6 +395,18 @@ static int http_options(const char *var, const char *value, void *cb)
return 0;
}

if (!strcmp("http.curloptresolve", var)) {
if (!value) {
return config_error_nonbool(var);
} else if (!*value) {
curl_slist_free_all(host_resolutions);
host_resolutions = NULL;
} else {
host_resolutions = curl_slist_append(host_resolutions, value);
}
return 0;
}

if (!strcmp("http.followredirects", var)) {
if (value && !strcmp(value, "initial"))
http_follow_config = HTTP_FOLLOW_INITIAL;
Expand Down Expand Up @@ -1131,6 +1145,9 @@ void http_cleanup(void)
curl_slist_free_all(no_pragma_header);
no_pragma_header = NULL;

curl_slist_free_all(host_resolutions);
host_resolutions = NULL;

if (curl_http_proxy) {
free((void *)curl_http_proxy);
curl_http_proxy = NULL;
Expand Down Expand Up @@ -1211,6 +1228,7 @@ struct active_request_slot *get_active_slot(void)
if (curl_save_cookies)
curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
curl_easy_setopt(slot->curl, CURLOPT_RESOLVE, host_resolutions);
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
Expand Down
7 changes: 7 additions & 0 deletions t/t5551-http-fetch-smart.sh
Expand Up @@ -567,4 +567,11 @@ test_expect_success 'client falls back from v2 to v0 to match server' '
grep symref=HEAD:refs/heads/ trace
'

test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
test_must_fail git ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null &&
git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
'

test_done

2 comments on commit 511cfd3

@FireBurn
Copy link

@FireBurn FireBurn commented on 511cfd3 Jun 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi

This breaks the build for me on RHEL6

    CC http.o
In file included from /usr/include/curl/curl.h:1933:0,
                 from git-curl-compat.h:3,
                 from http.c:2:
http.c: In function 'get_active_slot':
http.c:1231:31: error: 'CURLOPT_RESOLVE' undeclared (first use in this function)
  curl_easy_setopt(slot->curl, CURLOPT_RESOLVE, host_resolutions);
                               ^
http.c:1231:31: note: each undeclared identifier is reported only once for each function it appears in
make: *** [http.o] Error 1
> curl --version
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.44 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp 
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 

@dscho
Copy link
Member

@dscho dscho commented on 511cfd3 Jul 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FireBurn bug reports go to the Git mailing list. See https://git-scm.com/community.

Please sign in to comment.