git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <johannes.schindelin@gmx.de>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Jeff King <peff@peff.net>
Subject: [PATCH v2] http: support sending custom HTTP headers
Date: Tue, 26 Apr 2016 17:40:30 +0200 (CEST)	[thread overview]
Message-ID: <921e007f445476b27325c12a9e92fdd169a073b7.1461685158.git.johannes.schindelin@gmx.de> (raw)
In-Reply-To: <abe253758829795c285c2036196ebe7edd9bab34.1461589951.git.johannes.schindelin@gmx.de>

We introduce a way to send custom HTTP headers with all requests.

This allows us, for example, to send an extra token from build agents
for temporary access to private repositories. (This is the use case that
triggered this patch.)

This feature can be used like this:

	git -c http.extraheader='Secret: sssh!' fetch $URL $REF

As `curl_easy_setopt(..., CURLOPT_HTTPHEADER, ...)` overrides previous
calls' headers (instead of appending the headers, as this unsuspecting
developer thought initially), we piggyback onto the `Pragma:` setting by
default, and introduce the global helper `http_copy_default_headers()`
to help functions that want to specify HTTP headers themselves.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

Published-As: https://github.com/dscho/git/releases/tag/extra-http-headers-v2

 Documentation/config.txt |  6 ++++++
 http-push.c              | 10 +++++-----
 http.c                   | 28 +++++++++++++++++++++++++---
 http.h                   |  1 +
 remote-curl.c            |  4 ++--
 5 files changed, 39 insertions(+), 10 deletions(-)

Interdiff vs v1:

 diff --git a/Documentation/config.txt b/Documentation/config.txt
 index 42d2b50..37b9af7 100644
 --- a/Documentation/config.txt
 +++ b/Documentation/config.txt
 @@ -1655,6 +1655,12 @@ http.emptyAuth::
  	a username in the URL, as libcurl normally requires a username for
  	authentication.
  
 +http.extraHeader::
 +	Pass an additional HTTP header when communicating with a server.  If
 +	more than one such entry exists, all of them are added as extra headers.
 +	This feature is useful e.g. to increase security, or to allow
 +	time-limited access based on expiring tokens.
 +
  http.cookieFile::
  	File containing previously stored cookie lines which should be used
  	in the Git http session, if they match the server. The file format
 diff --git a/http-push.c b/http-push.c
 index 04eef17..ae2b7f1 100644
 --- a/http-push.c
 +++ b/http-push.c
 @@ -211,7 +211,7 @@ static void curl_setup_http(CURL *curl, const char *url,
  static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
  {
  	struct strbuf buf = STRBUF_INIT;
 -	struct curl_slist *dav_headers = http_get_default_headers();
 +	struct curl_slist *dav_headers = http_copy_default_headers();
  
  	if (options & DAV_HEADER_IF) {
  		strbuf_addf(&buf, "If: (<%s>)", lock->token);
 @@ -417,7 +417,7 @@ static void start_put(struct transfer_request *request)
  static void start_move(struct transfer_request *request)
  {
  	struct active_request_slot *slot;
 -	struct curl_slist *dav_headers = http_get_default_headers();
 +	struct curl_slist *dav_headers = http_copy_default_headers();
  
  	slot = get_active_slot();
  	slot->callback_func = process_response;
 @@ -845,7 +845,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
  	char *ep;
  	char timeout_header[25];
  	struct remote_lock *lock = NULL;
 -	struct curl_slist *dav_headers = http_get_default_headers();
 +	struct curl_slist *dav_headers = http_copy_default_headers();
  	struct xml_ctx ctx;
  	char *escaped;
  
 @@ -1126,7 +1126,7 @@ static void remote_ls(const char *path, int flags,
  	struct slot_results results;
  	struct strbuf in_buffer = STRBUF_INIT;
  	struct buffer out_buffer = { STRBUF_INIT, 0 };
 -	struct curl_slist *dav_headers = http_get_default_headers();
 +	struct curl_slist *dav_headers = http_copy_default_headers();
  	struct xml_ctx ctx;
  	struct remote_ls_ctx ls;
  
 @@ -1204,7 +1204,7 @@ static int locking_available(void)
  	struct slot_results results;
  	struct strbuf in_buffer = STRBUF_INIT;
  	struct buffer out_buffer = { STRBUF_INIT, 0 };
 -	struct curl_slist *dav_headers = http_get_default_headers();
 +	struct curl_slist *dav_headers = http_copy_default_headers();
  	struct xml_ctx ctx;
  	int lock_flags = 0;
  	char *escaped;
 diff --git a/http.c b/http.c
 index 02d7147..3d662bb 100644
 --- a/http.c
 +++ b/http.c
 @@ -685,9 +685,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
  	if (remote)
  		var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
  
 -	pragma_header = curl_slist_append(http_get_default_headers(),
 +	pragma_header = curl_slist_append(http_copy_default_headers(),
  		"Pragma: no-cache");
 -	no_pragma_header = curl_slist_append(http_get_default_headers(),
 +	no_pragma_header = curl_slist_append(http_copy_default_headers(),
  		"Pragma:");
  
  #ifdef USE_CURL_MULTI
 @@ -1175,7 +1175,7 @@ int run_one_slot(struct active_request_slot *slot,
  	return handle_curl_result(results);
  }
  
 -struct curl_slist *http_get_default_headers()
 +struct curl_slist *http_copy_default_headers()
  {
  	struct curl_slist *headers = NULL, *h;
  
 @@ -1402,7 +1402,7 @@ static int http_request(const char *url,
  {
  	struct active_request_slot *slot;
  	struct slot_results results;
 -	struct curl_slist *headers = http_get_default_headers();
 +	struct curl_slist *headers = http_copy_default_headers();
  	struct strbuf buf = STRBUF_INIT;
  	const char *accept_language;
  	int ret;
 diff --git a/http.h b/http.h
 index b0927de..5f13695 100644
 --- a/http.h
 +++ b/http.h
 @@ -106,7 +106,7 @@ extern void step_active_slots(void);
  extern void http_init(struct remote *remote, const char *url,
  		      int proactive_auth);
  extern void http_cleanup(void);
 -extern struct curl_slist *http_get_default_headers();
 +extern struct curl_slist *http_copy_default_headers();
  
  extern long int git_curl_ipresolve;
  extern int active_requests;
 diff --git a/remote-curl.c b/remote-curl.c
 index 86ba787..672b382 100644
 --- a/remote-curl.c
 +++ b/remote-curl.c
 @@ -474,7 +474,7 @@ static int run_slot(struct active_request_slot *slot,
  static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
  {
  	struct active_request_slot *slot;
 -	struct curl_slist *headers = http_get_default_headers();
 +	struct curl_slist *headers = http_copy_default_headers();
  	struct strbuf buf = STRBUF_INIT;
  	int err;
  
 @@ -503,7 +503,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
  static int post_rpc(struct rpc_state *rpc)
  {
  	struct active_request_slot *slot;
 -	struct curl_slist *headers = http_get_default_headers();
 +	struct curl_slist *headers = http_copy_default_headers();
  	int use_gzip = rpc->gzip_request;
  	char *gzip_body = NULL;
  	size_t gzip_size = 0;


diff --git a/Documentation/config.txt b/Documentation/config.txt
index 42d2b50..37b9af7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1655,6 +1655,12 @@ http.emptyAuth::
 	a username in the URL, as libcurl normally requires a username for
 	authentication.
 
+http.extraHeader::
+	Pass an additional HTTP header when communicating with a server.  If
+	more than one such entry exists, all of them are added as extra headers.
+	This feature is useful e.g. to increase security, or to allow
+	time-limited access based on expiring tokens.
+
 http.cookieFile::
 	File containing previously stored cookie lines which should be used
 	in the Git http session, if they match the server. The file format
diff --git a/http-push.c b/http-push.c
index bd60668..ae2b7f1 100644
--- a/http-push.c
+++ b/http-push.c
@@ -211,7 +211,7 @@ static void curl_setup_http(CURL *curl, const char *url,
 static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
 {
 	struct strbuf buf = STRBUF_INIT;
-	struct curl_slist *dav_headers = NULL;
+	struct curl_slist *dav_headers = http_copy_default_headers();
 
 	if (options & DAV_HEADER_IF) {
 		strbuf_addf(&buf, "If: (<%s>)", lock->token);
@@ -417,7 +417,7 @@ static void start_put(struct transfer_request *request)
 static void start_move(struct transfer_request *request)
 {
 	struct active_request_slot *slot;
-	struct curl_slist *dav_headers = NULL;
+	struct curl_slist *dav_headers = http_copy_default_headers();
 
 	slot = get_active_slot();
 	slot->callback_func = process_response;
@@ -845,7 +845,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
 	char *ep;
 	char timeout_header[25];
 	struct remote_lock *lock = NULL;
-	struct curl_slist *dav_headers = NULL;
+	struct curl_slist *dav_headers = http_copy_default_headers();
 	struct xml_ctx ctx;
 	char *escaped;
 
@@ -1126,7 +1126,7 @@ static void remote_ls(const char *path, int flags,
 	struct slot_results results;
 	struct strbuf in_buffer = STRBUF_INIT;
 	struct buffer out_buffer = { STRBUF_INIT, 0 };
-	struct curl_slist *dav_headers = NULL;
+	struct curl_slist *dav_headers = http_copy_default_headers();
 	struct xml_ctx ctx;
 	struct remote_ls_ctx ls;
 
@@ -1204,7 +1204,7 @@ static int locking_available(void)
 	struct slot_results results;
 	struct strbuf in_buffer = STRBUF_INIT;
 	struct buffer out_buffer = { STRBUF_INIT, 0 };
-	struct curl_slist *dav_headers = NULL;
+	struct curl_slist *dav_headers = http_copy_default_headers();
 	struct xml_ctx ctx;
 	int lock_flags = 0;
 	char *escaped;
diff --git a/http.c b/http.c
index 4304b80..3d662bb 100644
--- a/http.c
+++ b/http.c
@@ -114,6 +114,7 @@ static unsigned long http_auth_methods = CURLAUTH_ANY;
 
 static struct curl_slist *pragma_header;
 static struct curl_slist *no_pragma_header;
+static struct curl_slist *extra_http_headers;
 
 static struct active_request_slot *active_queue_head;
 
@@ -323,6 +324,12 @@ static int http_options(const char *var, const char *value, void *cb)
 #endif
 	}
 
+	if (!strcmp("http.extraheader", var)) {
+		extra_http_headers =
+			curl_slist_append(extra_http_headers, value);
+		return 0;
+	}
+
 	/* Fall back on the default ones */
 	return git_default_config(var, value, cb);
 }
@@ -678,8 +685,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 	if (remote)
 		var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
 
-	pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
-	no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
+	pragma_header = curl_slist_append(http_copy_default_headers(),
+		"Pragma: no-cache");
+	no_pragma_header = curl_slist_append(http_copy_default_headers(),
+		"Pragma:");
 
 #ifdef USE_CURL_MULTI
 	{
@@ -765,6 +774,9 @@ void http_cleanup(void)
 #endif
 	curl_global_cleanup();
 
+	curl_slist_free_all(extra_http_headers);
+	extra_http_headers = NULL;
+
 	curl_slist_free_all(pragma_header);
 	pragma_header = NULL;
 
@@ -1163,6 +1175,16 @@ int run_one_slot(struct active_request_slot *slot,
 	return handle_curl_result(results);
 }
 
+struct curl_slist *http_copy_default_headers()
+{
+	struct curl_slist *headers = NULL, *h;
+
+	for (h = extra_http_headers; h; h = h->next)
+		headers = curl_slist_append(headers, h->data);
+
+	return headers;
+}
+
 static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
 {
 	char *ptr;
@@ -1380,7 +1402,7 @@ static int http_request(const char *url,
 {
 	struct active_request_slot *slot;
 	struct slot_results results;
-	struct curl_slist *headers = NULL;
+	struct curl_slist *headers = http_copy_default_headers();
 	struct strbuf buf = STRBUF_INIT;
 	const char *accept_language;
 	int ret;
diff --git a/http.h b/http.h
index 4ef4bbd..5f13695 100644
--- a/http.h
+++ b/http.h
@@ -106,6 +106,7 @@ extern void step_active_slots(void);
 extern void http_init(struct remote *remote, const char *url,
 		      int proactive_auth);
 extern void http_cleanup(void);
+extern struct curl_slist *http_copy_default_headers();
 
 extern long int git_curl_ipresolve;
 extern int active_requests;
diff --git a/remote-curl.c b/remote-curl.c
index 15e48e2..672b382 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -474,7 +474,7 @@ static int run_slot(struct active_request_slot *slot,
 static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 {
 	struct active_request_slot *slot;
-	struct curl_slist *headers = NULL;
+	struct curl_slist *headers = http_copy_default_headers();
 	struct strbuf buf = STRBUF_INIT;
 	int err;
 
@@ -503,7 +503,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 static int post_rpc(struct rpc_state *rpc)
 {
 	struct active_request_slot *slot;
-	struct curl_slist *headers = NULL;
+	struct curl_slist *headers = http_copy_default_headers();
 	int use_gzip = rpc->gzip_request;
 	char *gzip_body = NULL;
 	size_t gzip_size = 0;
-- 
2.8.1.306.gff998f2

  parent reply	other threads:[~2016-04-26 15:40 UTC|newest]

Thread overview: 119+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-25 13:13 [PATCH] http: Support sending custom HTTP headers Johannes Schindelin
2016-04-25 15:53 ` Shawn Pearce
2016-04-25 17:03 ` Jeff King
2016-04-26 15:37   ` Johannes Schindelin
2016-04-26 16:57     ` Jeff King
2016-04-25 18:43 ` Junio C Hamano
2016-04-26 15:33   ` Johannes Schindelin
2016-04-26 16:22     ` Junio C Hamano
2016-04-26 17:38     ` Jeff King
2016-04-27  6:31       ` Johannes Schindelin
2016-04-27  7:52         ` Jeff King
2016-04-27 11:56           ` Johannes Schindelin
2016-04-26 15:40 ` Johannes Schindelin [this message]
2016-04-26 17:03   ` [PATCH v2] http: support " Junio C Hamano
2016-04-26 17:12     ` Jeff King
2016-04-26 17:20       ` Junio C Hamano
2016-04-26 17:44         ` Jeff King
2016-04-27  6:08           ` Johannes Schindelin
2016-04-27  6:29         ` Johannes Schindelin
2016-04-26 19:05   ` Junio C Hamano
2016-04-27  6:29   ` [PATCH v3] " Johannes Schindelin
2016-04-27 12:20     ` [PATCH v4] " Johannes Schindelin
2016-04-27 19:30       ` Jeff King
2016-04-27 21:03         ` Junio C Hamano
2016-04-28 10:03       ` [PATCH v5 0/2] Add support for sending additional " Johannes Schindelin
2016-04-28 10:03         ` [PATCH v5 1/2] http: support sending custom " Johannes Schindelin
2016-04-28 10:03         ` [PATCH v5 2/2] submodule: pass on http.extraheader config settings Johannes Schindelin
2016-04-28 11:29           ` Jeff King
2016-04-28 12:19             ` Johannes Schindelin
2016-04-28 13:49               ` Jeff King
2016-04-28 15:37                 ` Jacob Keller
2016-04-28 15:39                   ` Jeff King
2016-04-28 16:09                     ` Stefan Beller
2016-04-28 16:50                       ` Jeff King
2016-04-28 19:06                         ` Junio C Hamano
2016-04-28 19:10                           ` Jeff King
2016-04-28 19:28                             ` Junio C Hamano
2016-04-28 19:34                               ` Stefan Beller
2016-04-28 19:52                                 ` Junio C Hamano
2016-04-28 19:53                                   ` Junio C Hamano
2016-04-28 20:01                                   ` Stefan Beller
2016-04-28 22:47                                     ` Junio C Hamano
2016-04-28 21:03                                   ` Jeff King
2016-04-28 21:12                                     ` Stefan Beller
2016-04-28 22:44                                     ` Junio C Hamano
2016-04-29 13:35                                       ` Jeff King
2016-04-28 21:00                               ` Jeff King
2016-04-28 21:08                                 ` Stefan Beller
2016-04-28 21:20                                   ` Jeff King
2016-04-29 12:29                                 ` Johannes Schindelin
2016-04-29 13:26                                   ` Jeff King
2016-04-28 13:53               ` Jeff King
2016-04-28 19:41           ` Junio C Hamano
2016-04-29 12:35             ` Johannes Schindelin
2016-04-29 12:48               ` Johannes Schindelin
2016-04-29 13:10                 ` Jeff King
2016-04-29 15:56                   ` Johannes Schindelin
2016-05-04  6:14         ` [PATCH v6 0/2] Add support for sending additional HTTP headers Johannes Schindelin
2016-05-04  6:14           ` [PATCH v6 1/2] http: support sending custom " Johannes Schindelin
2016-05-05 19:10             ` Lars Schneider
2016-05-05 19:40               ` Junio C Hamano
2016-05-05 20:03               ` Jeff King
2016-05-04  6:14           ` [PATCH v6 2/2] submodule: pass on http.extraheader config settings Johannes Schindelin
2016-05-04  6:26           ` [PATCH v6 0/2] Add support for sending additional HTTP headers Jeff King
2016-05-04  7:36             ` Junio C Hamano
2016-05-04 11:20               ` Johannes Schindelin
2016-05-04 18:23                 ` Junio C Hamano
2016-05-04  7:45             ` Jeff King
2016-05-04  8:00               ` [PATCH] submodule: stop sanitizing config options Jeff King
2016-05-04  8:17                 ` Junio C Hamano
2016-05-04 11:25                   ` Johannes Schindelin
2016-05-04 17:58                 ` Stefan Beller
2016-05-04 19:04                   ` Jeff King
2016-05-04 18:43                 ` Junio C Hamano
2016-05-04 19:09                   ` Jeff King
2016-05-04 22:53                 ` Stefan Beller
2016-05-05  1:22                   ` Jeff King
2016-05-05 16:59                     ` Junio C Hamano
2016-05-05 20:14                       ` Jeff King
2016-05-05 23:33                         ` Junio C Hamano
2016-05-06  0:23                           ` Stefan Beller
2016-05-06  1:00                             ` Jeff King
2016-05-06 19:56                             ` Junio C Hamano
2016-05-09  6:18           ` [PATCH v7 0/3] Add support for sending additional HTTP headers (part 2) Johannes Schindelin
2016-05-09  6:18             ` [PATCH v7 1/3] tests: Adjust the configuration for Apache 2.2 Johannes Schindelin
2016-05-09  8:03               ` Jeff King
2016-05-09 14:03                 ` Johannes Schindelin
2016-05-09 14:27                   ` Jeff King
2016-05-09 15:11                     ` Johannes Schindelin
2016-05-09 16:42                       ` Junio C Hamano
2016-05-09 16:51                         ` Jeff King
2016-05-09 17:41                           ` Junio C Hamano
2016-05-10  6:53                         ` Johannes Schindelin
2016-05-10  7:13                           ` Junio C Hamano
2016-05-09 16:23               ` Junio C Hamano
2016-05-10  6:37               ` Lars Schneider
2016-05-10  7:14                 ` Junio C Hamano
2016-05-09  6:19             ` [PATCH v7 2/3] t5551: make the test for extra HTTP headers more robust Johannes Schindelin
2016-05-09  7:56               ` Lars Schneider
2016-05-09  8:05               ` Jeff King
2016-05-09  8:13                 ` Johannes Schindelin
2016-05-09  8:20                   ` Jeff King
2016-05-09  6:19             ` [PATCH v7 3/3] submodule: pass on http.extraheader config settings Johannes Schindelin
2016-05-10  7:08             ` [PATCH v8 0/3] Add support for sending additional HTTP headers (part 2) Johannes Schindelin
2016-05-10  7:08               ` [PATCH v8 1/3] tests: adjust the configuration for Apache 2.2 Johannes Schindelin
2016-05-10 17:31                 ` Junio C Hamano
2016-05-10  7:08               ` [PATCH v8 2/3] t5551: make the test for extra HTTP headers more robust Johannes Schindelin
2016-05-10 17:34                 ` Junio C Hamano
2016-05-11 17:13                 ` t5551 hangs ? Torsten Bögershausen
2016-05-11 17:31                   ` Jeff King
2016-05-11 20:03                     ` Torsten Bögershausen
2016-05-12  3:16                       ` Jeff King
2016-05-12  6:21                         ` Torsten Bögershausen
2016-05-12  6:40                           ` Jeff King
2016-05-12  7:29                             ` Jeff King
2016-05-10  7:08               ` [PATCH v8 3/3] submodule: ensure that -c http.extraheader is heeded Johannes Schindelin
2016-05-10 17:38                 ` Junio C Hamano
2016-05-11  6:57                   ` Johannes Schindelin
     [not found]             ` <34DE0A16-F0B2-4379-8E02-5235D34FDD76@gmail.com>
2016-05-16 13:35               ` mail-patch-series.sh, was Re: [PATCH v7 0/3] Add support for sending additional HTTP headers (part 2) Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=921e007f445476b27325c12a9e92fdd169a073b7.1461685158.git.johannes.schindelin@gmx.de \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).