# [PATCH] Prompt for a username when an HTTP request 401s

3 messages from 2010-03-18 to 2010-03-18. Participants: Scott Chacon, Shawn O. Pearce, René Scharfe.
Thread: https://gitlist.dev/t/23067

## Scott Chacon, 2010-03-18 18:57

Subject: [PATCH] Prompt for a username when an HTTP request 401s
Message-ID: <d411cc4a1003181157o79f1a1e1qcdea05322d76b812@mail.gmail.com>
URL: https://gitlist.dev/e/d411cc4a1003181157o79f1a1e1qcdea05322d76b812%40mail.gmail.com

```
When an HTTP request returns a 401, Git will currently fail with a
confusing message saying that it got a 401.  This changes
http_request to prompt for the username and password, then return
HTTP_REAUTH so http_get_strbuf can try again.  If it gets a 401 even
when a user/pass is supplied, http_request will now return HTTP_NOAUTH
which remote_curl can then use to display a more intelligent error
message that is less confusing.

Signed-off-by: Scott Chacon <schacon@gmail.com>
---
 http.c        |   21 +++++++++++++++++++--
 http.h        |    2 ++
 remote-curl.c |    2 ++
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/http.c b/http.c
index deab595..731783e 100644
--- a/http.c
+++ b/http.c
@@ -199,6 +199,11 @@ static int http_options(const char *var, const
char *value, void *cb)
 	return git_default_config(var, value, cb);
 }

+static void get_http_user_name()
+{
+	user_name = xstrdup(getpass("Username: "));
+}
+
 static void init_curl_http_auth(CURL *result)
 {
 	if (user_name) {
@@ -815,7 +820,15 @@ static int http_request(const char *url, void
*result, int target, int options)
 			ret = HTTP_OK;
 		else if (missing_target(&results))
 			ret = HTTP_MISSING_TARGET;
-		else
+		else if (results.http_code == 401) {
+			if (user_name) {
+				ret = HTTP_NOAUTH;
+			} else {
+				get_http_user_name();
+				init_curl_http_auth(slot->curl);
+				ret = HTTP_REAUTH;
+			}
+		} else
 			ret = HTTP_ERROR;
 	} else {
 		error("Unable to start HTTP request for %s", url);
@@ -831,7 +844,11 @@ static int http_request(const char *url, void
*result, int target, int options)

 int http_get_strbuf(const char *url, struct strbuf *result, int options)
 {
-	return http_request(url, result, HTTP_REQUEST_STRBUF, options);
+	int http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+	if (http_ret == HTTP_REAUTH) {
+		http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+	}
+	return http_ret;
 }

 /*
diff --git a/http.h b/http.h
index 5c9441c..2dd03e8 100644
--- a/http.h
+++ b/http.h
@@ -126,6 +126,8 @@ extern char *get_remote_object_url(const char
*url, const char *hex,
 #define HTTP_MISSING_TARGET	1
 #define HTTP_ERROR		2
 #define HTTP_START_FAILED	3
+#define HTTP_REAUTH	4
+#define HTTP_NOAUTH	5

 /*
  * Requests an url and stores the result in a strbuf.
diff --git a/remote-curl.c b/remote-curl.c
index b76bfcb..0782756 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -132,6 +132,8 @@ static struct discovery* discover_refs(const char *service)
 	case HTTP_MISSING_TARGET:
 		die("%s not found: did you run git update-server-info on the"
 		    " server?", refs_url);
+	case HTTP_NOAUTH:
+		die("Authentication failed");
 	default:
 		http_error(refs_url, http_ret);
 		die("HTTP request failed");
-- 
1.7.0.1

```

## Shawn O. Pearce, 2010-03-18 19:03

Subject: Re: [PATCH] Prompt for a username when an HTTP request 401s
Message-ID: <20100318190309.GC10981@spearce.org>
URL: https://gitlist.dev/e/20100318190309.GC10981%40spearce.org
In-Reply-To: <d411cc4a1003181157o79f1a1e1qcdea05322d76b812@mail.gmail.com>

```
Scott Chacon <schacon@gmail.com> wrote:
> When an HTTP request returns a 401, Git will currently fail with a
> confusing message saying that it got a 401.  This changes
> http_request to prompt for the username and password, then return
> HTTP_REAUTH so http_get_strbuf can try again.  If it gets a 401 even
> when a user/pass is supplied, http_request will now return HTTP_NOAUTH
> which remote_curl can then use to display a more intelligent error
> message that is less confusing.
> 
> Signed-off-by: Scott Chacon <schacon@gmail.com>
> ---
>  http.c        |   21 +++++++++++++++++++--
>  http.h        |    2 ++
>  remote-curl.c |    2 ++
>  3 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/http.c b/http.c
> index deab595..731783e 100644
> --- a/http.c
> +++ b/http.c
> @@ -199,6 +199,11 @@ static int http_options(const char *var, const
> char *value, void *cb)
>  	return git_default_config(var, value, cb);
>  }
> 
> +static void get_http_user_name()
> +{
> +	user_name = xstrdup(getpass("Username: "));

Why are we getting the username via a password prompt where echo
has been disabled?  Traditionally a username field is obtained as
echoed input.

Also, this method shouldn't be named get_*() if its returning void.
Sounds far to funny.  init_http_user_name()?  prompt_for_user_name()?

-- 
Shawn.

```

## René Scharfe, 2010-03-18 23:53

Subject: Re: [PATCH] Prompt for a username when an HTTP request 401s
Message-ID: <4BA2BCFC.9070600@lsrfire.ath.cx>
URL: https://gitlist.dev/e/4BA2BCFC.9070600%40lsrfire.ath.cx
In-Reply-To: <20100318190309.GC10981@spearce.org>

```
Am 18.03.2010 20:03, schrieb Shawn O. Pearce:
> Scott Chacon <schacon@gmail.com> wrote:
>> +static void get_http_user_name()
>> +{
>> +	user_name = xstrdup(getpass("Username: "));
> 
> Why are we getting the username via a password prompt where echo
> has been disabled?  Traditionally a username field is obtained as
> echoed input.
> 
> Also, this method shouldn't be named get_*() if its returning void.
> Sounds far to funny.  init_http_user_name()?  prompt_for_user_name()?

Or inline the one-liner at its single call-site?

René

```
