http.c: implement the GIT_TRACE_CURL environment variable
Implement the GIT_TRACE_CURL environment variable to allow a greater degree of detail of GIT_CURL_VERBOSE, in particular the complete transport header and all the data payload exchanged. It might be useful if a particular situation could require a more thorough debugging analysis. Document the new GIT_TRACE_CURL environment variable. Helped-by: Torsten Bögershausen <tboegi@web.de> Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Helped-by: Jeff King <peff@peff.net> Signed-off-by: Elia Pinto <gitter.spiros@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
e6ac6e1f7d
commit
74c682d3c6
@ -1075,6 +1075,14 @@ of clones and fetches.
|
||||
cloning of shallow repositories.
|
||||
See 'GIT_TRACE' for available trace output options.
|
||||
|
||||
'GIT_TRACE_CURL'::
|
||||
Enables a curl full trace dump of all incoming and outgoing data,
|
||||
including descriptive information, of the git transport protocol.
|
||||
This is similar to doing curl --trace-ascii on the command line.
|
||||
This option overrides setting the GIT_CURL_VERBOSE environment
|
||||
variable.
|
||||
See 'GIT_TRACE' for available trace output options.
|
||||
|
||||
'GIT_LITERAL_PATHSPECS'::
|
||||
Setting this variable to `1` will cause Git to treat all
|
||||
pathspecs literally, rather than as glob patterns. For example,
|
||||
|
124
http.c
124
http.c
@ -11,6 +11,7 @@
|
||||
#include "gettext.h"
|
||||
#include "transport.h"
|
||||
|
||||
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
|
||||
#if LIBCURL_VERSION_NUM >= 0x070a08
|
||||
long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
|
||||
#else
|
||||
@ -464,6 +465,125 @@ static void set_curl_keepalive(CURL *c)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void redact_sensitive_header(struct strbuf *header)
|
||||
{
|
||||
const char *sensitive_header;
|
||||
|
||||
if (skip_prefix(header->buf, "Authorization:", &sensitive_header) ||
|
||||
skip_prefix(header->buf, "Proxy-Authorization:", &sensitive_header)) {
|
||||
/* The first token is the type, which is OK to log */
|
||||
while (isspace(*sensitive_header))
|
||||
sensitive_header++;
|
||||
while (*sensitive_header && !isspace(*sensitive_header))
|
||||
sensitive_header++;
|
||||
/* Everything else is opaque and possibly sensitive */
|
||||
strbuf_setlen(header, sensitive_header - header->buf);
|
||||
strbuf_addstr(header, " <redacted>");
|
||||
}
|
||||
}
|
||||
|
||||
static void curl_dump_header(const char *text, unsigned char *ptr, size_t size, int hide_sensitive_header)
|
||||
{
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
struct strbuf **headers, **header;
|
||||
|
||||
strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n",
|
||||
text, (long)size, (long)size);
|
||||
trace_strbuf(&trace_curl, &out);
|
||||
strbuf_reset(&out);
|
||||
strbuf_add(&out, ptr, size);
|
||||
headers = strbuf_split_max(&out, '\n', 0);
|
||||
|
||||
for (header = headers; *header; header++) {
|
||||
if (hide_sensitive_header)
|
||||
redact_sensitive_header(*header);
|
||||
strbuf_insert((*header), 0, text, strlen(text));
|
||||
strbuf_insert((*header), strlen(text), ": ", 2);
|
||||
strbuf_rtrim((*header));
|
||||
strbuf_addch((*header), '\n');
|
||||
trace_strbuf(&trace_curl, (*header));
|
||||
}
|
||||
strbuf_list_free(headers);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static void curl_dump_data(const char *text, unsigned char *ptr, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
struct strbuf out = STRBUF_INIT;
|
||||
unsigned int width = 60;
|
||||
|
||||
strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n",
|
||||
text, (long)size, (long)size);
|
||||
trace_strbuf(&trace_curl, &out);
|
||||
|
||||
for (i = 0; i < size; i += width) {
|
||||
size_t w;
|
||||
|
||||
strbuf_reset(&out);
|
||||
strbuf_addf(&out, "%s: ", text);
|
||||
for (w = 0; (w < width) && (i + w < size); w++) {
|
||||
unsigned char ch = ptr[i + w];
|
||||
|
||||
strbuf_addch(&out,
|
||||
(ch >= 0x20) && (ch < 0x80)
|
||||
? ch : '.');
|
||||
}
|
||||
strbuf_addch(&out, '\n');
|
||||
trace_strbuf(&trace_curl, &out);
|
||||
}
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
|
||||
{
|
||||
const char *text;
|
||||
enum { NO_FILTER = 0, DO_FILTER = 1 };
|
||||
|
||||
switch (type) {
|
||||
case CURLINFO_TEXT:
|
||||
trace_printf_key(&trace_curl, "== Info: %s", data);
|
||||
default: /* we ignore unknown types by default */
|
||||
return 0;
|
||||
|
||||
case CURLINFO_HEADER_OUT:
|
||||
text = "=> Send header";
|
||||
curl_dump_header(text, (unsigned char *)data, size, DO_FILTER);
|
||||
break;
|
||||
case CURLINFO_DATA_OUT:
|
||||
text = "=> Send data";
|
||||
curl_dump_data(text, (unsigned char *)data, size);
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
text = "=> Send SSL data";
|
||||
curl_dump_data(text, (unsigned char *)data, size);
|
||||
break;
|
||||
case CURLINFO_HEADER_IN:
|
||||
text = "<= Recv header";
|
||||
curl_dump_header(text, (unsigned char *)data, size, NO_FILTER);
|
||||
break;
|
||||
case CURLINFO_DATA_IN:
|
||||
text = "<= Recv data";
|
||||
curl_dump_data(text, (unsigned char *)data, size);
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
text = "<= Recv SSL data";
|
||||
curl_dump_data(text, (unsigned char *)data, size);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup_curl_trace(CURL *handle)
|
||||
{
|
||||
if (!trace_want(&trace_curl))
|
||||
return;
|
||||
curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, curl_trace);
|
||||
curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL);
|
||||
}
|
||||
|
||||
|
||||
static CURL *get_curl_handle(void)
|
||||
{
|
||||
CURL *result = curl_easy_init();
|
||||
@ -562,9 +682,9 @@ static CURL *get_curl_handle(void)
|
||||
warning("protocol restrictions not applied to curl redirects because\n"
|
||||
"your curl version is too old (>= 7.19.4)");
|
||||
#endif
|
||||
|
||||
if (getenv("GIT_CURL_VERBOSE"))
|
||||
curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
|
||||
curl_easy_setopt(result, CURLOPT_VERBOSE, 1L);
|
||||
setup_curl_trace(result);
|
||||
|
||||
curl_easy_setopt(result, CURLOPT_USERAGENT,
|
||||
user_agent ? user_agent : git_user_agent());
|
||||
|
2
http.h
2
http.h
@ -224,4 +224,6 @@ extern int finish_http_object_request(struct http_object_request *freq);
|
||||
extern void abort_http_object_request(struct http_object_request *freq);
|
||||
extern void release_http_object_request(struct http_object_request *freq);
|
||||
|
||||
/* setup routine for curl_easy_setopt CURLOPT_DEBUGFUNCTION */
|
||||
void setup_curl_trace(CURL *handle);
|
||||
#endif /* HTTP_H */
|
||||
|
Loading…
Reference in New Issue
Block a user