{"thread":{"id":"23067","subject":"[PATCH] Prompt for a username when an HTTP request 401s","startedAt":"2010-03-18T18:57:34Z","lastAt":"2010-03-18T23:53:32Z","messageCount":3,"participants":["Scott Chacon","Shawn O. Pearce","René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"137111","messageId":"d411cc4a1003181157o79f1a1e1qcdea05322d76b812@mail.gmail.com","threadId":"23067","inReplyTo":null,"subject":"[PATCH] Prompt for a username when an HTTP request 401s","fromName":"Scott Chacon","fromEmail":"schacon@gmail.com","sentAt":"2010-03-18T18:57:34Z","receivedAt":"2010-03-18T18:57:34Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"When an HTTP request returns a 401, Git will currently fail with a\nconfusing message saying that it got a 401.  This changes\nhttp_request to prompt for the username and password, then return\nHTTP_REAUTH so http_get_strbuf can try again.  If it gets a 401 even\nwhen a user/pass is supplied, http_request will now return HTTP_NOAUTH\nwhich remote_curl can then use to display a more intelligent error\nmessage that is less confusing.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n http.c        |   21 +++++++++++++++++++--\n http.h        |    2 ++\n remote-curl.c |    2 ++\n 3 files changed, 23 insertions(+), 2 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex deab595..731783e 100644\n--- a/http.c\n+++ b/http.c\n@@ -199,6 +199,11 @@ static int http_options(const char *var, const\nchar *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n\n+static void get_http_user_name()\n+{\n+\tuser_name = xstrdup(getpass(\"Username: \"));\n+}\n+\n static void init_curl_http_auth(CURL *result)\n {\n \tif (user_name) {\n@@ -815,7 +820,15 @@ static int http_request(const char *url, void\n*result, int target, int options)\n \t\t\tret = HTTP_OK;\n \t\telse if (missing_target(&results))\n \t\t\tret = HTTP_MISSING_TARGET;\n-\t\telse\n+\t\telse if (results.http_code == 401) {\n+\t\t\tif (user_name) {\n+\t\t\t\tret = HTTP_NOAUTH;\n+\t\t\t} else {\n+\t\t\t\tget_http_user_name();\n+\t\t\t\tinit_curl_http_auth(slot->curl);\n+\t\t\t\tret = HTTP_REAUTH;\n+\t\t\t}\n+\t\t} else\n \t\t\tret = HTTP_ERROR;\n \t} else {\n \t\terror(\"Unable to start HTTP request for %s\", url);\n@@ -831,7 +844,11 @@ static int http_request(const char *url, void\n*result, int target, int options)\n\n int http_get_strbuf(const char *url, struct strbuf *result, int options)\n {\n-\treturn http_request(url, result, HTTP_REQUEST_STRBUF, options);\n+\tint http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);\n+\tif (http_ret == HTTP_REAUTH) {\n+\t\thttp_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);\n+\t}\n+\treturn http_ret;\n }\n\n /*\ndiff --git a/http.h b/http.h\nindex 5c9441c..2dd03e8 100644\n--- a/http.h\n+++ b/http.h\n@@ -126,6 +126,8 @@ extern char *get_remote_object_url(const char\n*url, const char *hex,\n #define HTTP_MISSING_TARGET\t1\n #define HTTP_ERROR\t\t2\n #define HTTP_START_FAILED\t3\n+#define HTTP_REAUTH\t4\n+#define HTTP_NOAUTH\t5\n\n /*\n  * Requests an url and stores the result in a strbuf.\ndiff --git a/remote-curl.c b/remote-curl.c\nindex b76bfcb..0782756 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -132,6 +132,8 @@ static struct discovery* discover_refs(const char *service)\n \tcase HTTP_MISSING_TARGET:\n \t\tdie(\"%s not found: did you run git update-server-info on the\"\n \t\t    \" server?\", refs_url);\n+\tcase HTTP_NOAUTH:\n+\t\tdie(\"Authentication failed\");\n \tdefault:\n \t\thttp_error(refs_url, http_ret);\n \t\tdie(\"HTTP request failed\");\n-- \n1.7.0.1\n"},{"id":"137115","messageId":"20100318190309.GC10981@spearce.org","threadId":"23067","inReplyTo":"d411cc4a1003181157o79f1a1e1qcdea05322d76b812@mail.gmail.com","subject":"Re: [PATCH] Prompt for a username when an HTTP request 401s","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2010-03-18T19:03:09Z","receivedAt":"2010-03-18T19:03:09Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Scott Chacon <schacon@gmail.com> wrote:\n> When an HTTP request returns a 401, Git will currently fail with a\n> confusing message saying that it got a 401.  This changes\n> http_request to prompt for the username and password, then return\n> HTTP_REAUTH so http_get_strbuf can try again.  If it gets a 401 even\n> when a user/pass is supplied, http_request will now return HTTP_NOAUTH\n> which remote_curl can then use to display a more intelligent error\n> message that is less confusing.\n> \n> Signed-off-by: Scott Chacon <schacon@gmail.com>\n> ---\n>  http.c        |   21 +++++++++++++++++++--\n>  http.h        |    2 ++\n>  remote-curl.c |    2 ++\n>  3 files changed, 23 insertions(+), 2 deletions(-)\n> \n> diff --git a/http.c b/http.c\n> index deab595..731783e 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -199,6 +199,11 @@ static int http_options(const char *var, const\n> char *value, void *cb)\n>  \treturn git_default_config(var, value, cb);\n>  }\n> \n> +static void get_http_user_name()\n> +{\n> +\tuser_name = xstrdup(getpass(\"Username: \"));\n\nWhy are we getting the username via a password prompt where echo\nhas been disabled?  Traditionally a username field is obtained as\nechoed input.\n\nAlso, this method shouldn't be named get_*() if its returning void.\nSounds far to funny.  init_http_user_name()?  prompt_for_user_name()?\n\n-- \nShawn.\n"},{"id":"137163","messageId":"4BA2BCFC.9070600@lsrfire.ath.cx","threadId":"23067","inReplyTo":"20100318190309.GC10981@spearce.org","subject":"Re: [PATCH] Prompt for a username when an HTTP request 401s","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2010-03-18T23:53:32Z","receivedAt":"2010-03-18T23:53:32Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 18.03.2010 20:03, schrieb Shawn O. Pearce:\n> Scott Chacon <schacon@gmail.com> wrote:\n>> +static void get_http_user_name()\n>> +{\n>> +\tuser_name = xstrdup(getpass(\"Username: \"));\n> \n> Why are we getting the username via a password prompt where echo\n> has been disabled?  Traditionally a username field is obtained as\n> echoed input.\n> \n> Also, this method shouldn't be named get_*() if its returning void.\n> Sounds far to funny.  init_http_user_name()?  prompt_for_user_name()?\n\nOr inline the one-liner at its single call-site?\n\nRené\n"}]}