Skip to content

Commit

Permalink
remote-curl: send Accept-Language header to server
Browse files Browse the repository at this point in the history
Git server end's ability to accept Accept-Language header was introduced
in f18604b (http: add Accept-Language header if possible, 2015-01-28),
but this is only used by very early phase of the transfer, which is HTTP
GET request to discover references. For other phases, like POST request
in the smart HTTP, the server does not know what language the client
speaks.

Teach git client to learn end-user's preferred language and throw
accept-language header to the server side. Once the server gets this header,
it has the ability to talk to end-user with language they understand.
This would be very helpful for many non-English speakers.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Li Linchao <lilinchao@oschina.cn>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Li Linchao authored and gitster committed Jul 11, 2022
1 parent 1e59178 commit b0c4adc
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 8 deletions.
4 changes: 2 additions & 2 deletions http.c
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,7 @@ static void write_accept_language(struct strbuf *buf)
* LANGUAGE= LANG=en_US.UTF-8 -> "Accept-Language: en-US, *; q=0.1"
* LANGUAGE= LANG=C -> ""
*/
static const char *get_accept_language(void)
const char *http_get_accept_language_header(void)
{
if (!cached_accept_language) {
struct strbuf buf = STRBUF_INIT;
Expand Down Expand Up @@ -1829,7 +1829,7 @@ static int http_request(const char *url,
fwrite_buffer);
}

accept_language = get_accept_language();
accept_language = http_get_accept_language_header();

if (accept_language)
headers = curl_slist_append(headers, accept_language);
Expand Down
3 changes: 3 additions & 0 deletions http.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ int http_fetch_ref(const char *base, struct ref *ref);
int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);

/* Helper for getting Accept-Language header */
const char *http_get_accept_language_header(void);

struct http_pack_request {
char *url;

Expand Down
21 changes: 18 additions & 3 deletions remote-curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ struct rpc_state {
char *service_url;
char *hdr_content_type;
char *hdr_accept;
char *hdr_accept_language;
char *protocol_header;
char *buf;
size_t alloc;
Expand Down Expand Up @@ -607,6 +608,8 @@ struct rpc_state {
unsigned flush_read_but_not_sent : 1;
};

#define RPC_STATE_INIT { 0 }

/*
* Appends the result of reading from rpc->out to the string represented by
* rpc->buf and rpc->len if there is enough space. Returns 1 if there was
Expand Down Expand Up @@ -932,6 +935,10 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece
headers = curl_slist_append(headers, needs_100_continue ?
"Expect: 100-continue" : "Expect:");

/* Add Accept-Language header */
if (rpc->hdr_accept_language)
headers = curl_slist_append(headers, rpc->hdr_accept_language);

/* Add the extra Git-Protocol header */
if (rpc->protocol_header)
headers = curl_slist_append(headers, rpc->protocol_header);
Expand Down Expand Up @@ -1080,6 +1087,8 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
strbuf_addf(&buf, "%s%s", url.buf, svc);
rpc->service_url = strbuf_detach(&buf, NULL);

rpc->hdr_accept_language = xstrdup_or_null(http_get_accept_language_header());

strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
rpc->hdr_content_type = strbuf_detach(&buf, NULL);

Expand Down Expand Up @@ -1118,6 +1127,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
free(rpc->service_url);
free(rpc->hdr_content_type);
free(rpc->hdr_accept);
free(rpc->hdr_accept_language);
free(rpc->protocol_header);
free(rpc->buf);
strbuf_release(&buf);
Expand Down Expand Up @@ -1153,7 +1163,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
static int fetch_git(struct discovery *heads,
int nr_heads, struct ref **to_fetch)
{
struct rpc_state rpc;
struct rpc_state rpc = RPC_STATE_INIT;
struct strbuf preamble = STRBUF_INIT;
int i, err;
struct strvec args = STRVEC_INIT;
Expand Down Expand Up @@ -1299,7 +1309,7 @@ static int push_dav(int nr_spec, const char **specs)

static int push_git(struct discovery *heads, int nr_spec, const char **specs)
{
struct rpc_state rpc;
struct rpc_state rpc = RPC_STATE_INIT;
int i, err;
struct strvec args;
struct string_list_item *cas_option;
Expand Down Expand Up @@ -1398,8 +1408,9 @@ static void parse_push(struct strbuf *buf)
static int stateless_connect(const char *service_name)
{
struct discovery *discover;
struct rpc_state rpc;
struct rpc_state rpc = RPC_STATE_INIT;
struct strbuf buf = STRBUF_INIT;
const char *accept_language;

/*
* Run the info/refs request and see if the server supports protocol
Expand All @@ -1418,6 +1429,9 @@ static int stateless_connect(const char *service_name)
printf("\n");
fflush(stdout);
}
accept_language = http_get_accept_language_header();
if (accept_language)
rpc.hdr_accept_language = xstrfmt("%s", accept_language);

rpc.service_name = service_name;
rpc.service_url = xstrfmt("%s%s", url.buf, rpc.service_name);
Expand Down Expand Up @@ -1467,6 +1481,7 @@ static int stateless_connect(const char *service_name)
free(rpc.service_url);
free(rpc.hdr_content_type);
free(rpc.hdr_accept);
free(rpc.hdr_accept_language);
free(rpc.protocol_header);
free(rpc.buf);
strbuf_release(&buf);
Expand Down
19 changes: 19 additions & 0 deletions t/t5541-http-push-smart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ test_expect_success 'push to remote repository (standard)' '
test $HEAD = $(git rev-parse --verify HEAD))
'

test_expect_success 'push to remote repository (standard) with sending Accept-Language' '
cat >exp <<-\EOF &&
=> Send header: Accept-Language: ko-KR, *;q=0.9
=> Send header: Accept-Language: ko-KR, *;q=0.9
EOF
cd "$ROOT_PATH"/test_repo_clone &&
: >path_lang &&
git add path_lang &&
test_tick &&
git commit -m path_lang &&
HEAD=$(git rev-parse --verify HEAD) &&
GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" git push -v -v 2>err &&
! grep "Expect: 100-continue" err &&
grep "=> Send header: Accept-Language:" err >err.language &&
test_cmp exp err.language
'

test_expect_success 'push already up-to-date' '
git push
'
Expand Down
2 changes: 1 addition & 1 deletion t/t5550-http-fetch-dumb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ ja;q=0.95, zh;q=0.94, sv;q=0.93, pt;q=0.92, nb;q=0.91, *;q=0.90" \
ko_KR.EUC-KR:en_US.UTF-8:fr_CA:de.UTF-8@euro:sr@latin:ja:zh:sv:pt:nb
'

test_expect_success 'git client does not send an empty Accept-Language' '
test_expect_success 'git client send an empty Accept-Language' '
GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
! grep "^=> Send header: Accept-Language:" stderr
'
Expand Down
10 changes: 8 additions & 2 deletions t/t5551-http-fetch-smart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ test_expect_success 'clone http repository' '
> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
> Accept: */*
> Accept-Encoding: ENCODINGS
> Accept-Language: ko-KR, *;q=0.9
> Pragma: no-cache
< HTTP/1.1 200 OK
< Pragma: no-cache
Expand All @@ -40,13 +41,15 @@ test_expect_success 'clone http repository' '
> Accept-Encoding: ENCODINGS
> Content-Type: application/x-git-upload-pack-request
> Accept: application/x-git-upload-pack-result
> Accept-Language: ko-KR, *;q=0.9
> Content-Length: xxx
< HTTP/1.1 200 OK
< Pragma: no-cache
< Cache-Control: no-cache, max-age=0, must-revalidate
< Content-Type: application/x-git-upload-pack-result
EOF
GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 \
GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 LANGUAGE="ko_KR.UTF-8" \
git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
test_cmp file clone/file &&
tr '\''\015'\'' Q <err |
Expand Down Expand Up @@ -94,7 +97,10 @@ test_expect_success 'clone http repository' '
test_cmp exp actual.smudged &&
grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
test_line_count = 2 actual.gzip
test_line_count = 2 actual.gzip &&
grep "Accept-Language: ko-KR, *" actual >actual.language &&
test_line_count = 2 actual.language
fi
'

Expand Down

0 comments on commit b0c4adc

Please sign in to comment.