Skip to content

Commit b0c4adc

Browse files
Li Linchaogitster
authored andcommitted
remote-curl: send Accept-Language header to server
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 <[email protected]> Signed-off-by: Li Linchao <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1e59178 commit b0c4adc

File tree

6 files changed

+51
-8
lines changed

6 files changed

+51
-8
lines changed

http.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,7 +1775,7 @@ static void write_accept_language(struct strbuf *buf)
17751775
* LANGUAGE= LANG=en_US.UTF-8 -> "Accept-Language: en-US, *; q=0.1"
17761776
* LANGUAGE= LANG=C -> ""
17771777
*/
1778-
static const char *get_accept_language(void)
1778+
const char *http_get_accept_language_header(void)
17791779
{
17801780
if (!cached_accept_language) {
17811781
struct strbuf buf = STRBUF_INIT;
@@ -1829,7 +1829,7 @@ static int http_request(const char *url,
18291829
fwrite_buffer);
18301830
}
18311831

1832-
accept_language = get_accept_language();
1832+
accept_language = http_get_accept_language_header();
18331833

18341834
if (accept_language)
18351835
headers = curl_slist_append(headers, accept_language);

http.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ int http_fetch_ref(const char *base, struct ref *ref);
178178
int http_get_info_packs(const char *base_url,
179179
struct packed_git **packs_head);
180180

181+
/* Helper for getting Accept-Language header */
182+
const char *http_get_accept_language_header(void);
183+
181184
struct http_pack_request {
182185
char *url;
183186

remote-curl.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ struct rpc_state {
580580
char *service_url;
581581
char *hdr_content_type;
582582
char *hdr_accept;
583+
char *hdr_accept_language;
583584
char *protocol_header;
584585
char *buf;
585586
size_t alloc;
@@ -607,6 +608,8 @@ struct rpc_state {
607608
unsigned flush_read_but_not_sent : 1;
608609
};
609610

611+
#define RPC_STATE_INIT { 0 }
612+
610613
/*
611614
* Appends the result of reading from rpc->out to the string represented by
612615
* rpc->buf and rpc->len if there is enough space. Returns 1 if there was
@@ -932,6 +935,10 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece
932935
headers = curl_slist_append(headers, needs_100_continue ?
933936
"Expect: 100-continue" : "Expect:");
934937

938+
/* Add Accept-Language header */
939+
if (rpc->hdr_accept_language)
940+
headers = curl_slist_append(headers, rpc->hdr_accept_language);
941+
935942
/* Add the extra Git-Protocol header */
936943
if (rpc->protocol_header)
937944
headers = curl_slist_append(headers, rpc->protocol_header);
@@ -1080,6 +1087,8 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
10801087
strbuf_addf(&buf, "%s%s", url.buf, svc);
10811088
rpc->service_url = strbuf_detach(&buf, NULL);
10821089

1090+
rpc->hdr_accept_language = xstrdup_or_null(http_get_accept_language_header());
1091+
10831092
strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
10841093
rpc->hdr_content_type = strbuf_detach(&buf, NULL);
10851094

@@ -1118,6 +1127,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
11181127
free(rpc->service_url);
11191128
free(rpc->hdr_content_type);
11201129
free(rpc->hdr_accept);
1130+
free(rpc->hdr_accept_language);
11211131
free(rpc->protocol_header);
11221132
free(rpc->buf);
11231133
strbuf_release(&buf);
@@ -1153,7 +1163,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
11531163
static int fetch_git(struct discovery *heads,
11541164
int nr_heads, struct ref **to_fetch)
11551165
{
1156-
struct rpc_state rpc;
1166+
struct rpc_state rpc = RPC_STATE_INIT;
11571167
struct strbuf preamble = STRBUF_INIT;
11581168
int i, err;
11591169
struct strvec args = STRVEC_INIT;
@@ -1299,7 +1309,7 @@ static int push_dav(int nr_spec, const char **specs)
12991309

13001310
static int push_git(struct discovery *heads, int nr_spec, const char **specs)
13011311
{
1302-
struct rpc_state rpc;
1312+
struct rpc_state rpc = RPC_STATE_INIT;
13031313
int i, err;
13041314
struct strvec args;
13051315
struct string_list_item *cas_option;
@@ -1398,8 +1408,9 @@ static void parse_push(struct strbuf *buf)
13981408
static int stateless_connect(const char *service_name)
13991409
{
14001410
struct discovery *discover;
1401-
struct rpc_state rpc;
1411+
struct rpc_state rpc = RPC_STATE_INIT;
14021412
struct strbuf buf = STRBUF_INIT;
1413+
const char *accept_language;
14031414

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

14221436
rpc.service_name = service_name;
14231437
rpc.service_url = xstrfmt("%s%s", url.buf, rpc.service_name);
@@ -1467,6 +1481,7 @@ static int stateless_connect(const char *service_name)
14671481
free(rpc.service_url);
14681482
free(rpc.hdr_content_type);
14691483
free(rpc.hdr_accept);
1484+
free(rpc.hdr_accept_language);
14701485
free(rpc.protocol_header);
14711486
free(rpc.buf);
14721487
strbuf_release(&buf);

t/t5541-http-push-smart.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ test_expect_success 'push to remote repository (standard)' '
8080
test $HEAD = $(git rev-parse --verify HEAD))
8181
'
8282

83+
test_expect_success 'push to remote repository (standard) with sending Accept-Language' '
84+
cat >exp <<-\EOF &&
85+
=> Send header: Accept-Language: ko-KR, *;q=0.9
86+
=> Send header: Accept-Language: ko-KR, *;q=0.9
87+
EOF
88+
89+
cd "$ROOT_PATH"/test_repo_clone &&
90+
: >path_lang &&
91+
git add path_lang &&
92+
test_tick &&
93+
git commit -m path_lang &&
94+
HEAD=$(git rev-parse --verify HEAD) &&
95+
GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" git push -v -v 2>err &&
96+
! grep "Expect: 100-continue" err &&
97+
98+
grep "=> Send header: Accept-Language:" err >err.language &&
99+
test_cmp exp err.language
100+
'
101+
83102
test_expect_success 'push already up-to-date' '
84103
git push
85104
'

t/t5550-http-fetch-dumb.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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" \
369369
ko_KR.EUC-KR:en_US.UTF-8:fr_CA:de.UTF-8@euro:sr@latin:ja:zh:sv:pt:nb
370370
'
371371

372-
test_expect_success 'git client does not send an empty Accept-Language' '
372+
test_expect_success 'git client send an empty Accept-Language' '
373373
GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
374374
! grep "^=> Send header: Accept-Language:" stderr
375375
'

t/t5551-http-fetch-smart.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ test_expect_success 'clone http repository' '
3131
> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
3232
> Accept: */*
3333
> Accept-Encoding: ENCODINGS
34+
> Accept-Language: ko-KR, *;q=0.9
3435
> Pragma: no-cache
3536
< HTTP/1.1 200 OK
3637
< Pragma: no-cache
@@ -40,13 +41,15 @@ test_expect_success 'clone http repository' '
4041
> Accept-Encoding: ENCODINGS
4142
> Content-Type: application/x-git-upload-pack-request
4243
> Accept: application/x-git-upload-pack-result
44+
> Accept-Language: ko-KR, *;q=0.9
4345
> Content-Length: xxx
4446
< HTTP/1.1 200 OK
4547
< Pragma: no-cache
4648
< Cache-Control: no-cache, max-age=0, must-revalidate
4749
< Content-Type: application/x-git-upload-pack-result
4850
EOF
49-
GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 \
51+
52+
GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 LANGUAGE="ko_KR.UTF-8" \
5053
git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
5154
test_cmp file clone/file &&
5255
tr '\''\015'\'' Q <err |
@@ -94,7 +97,10 @@ test_expect_success 'clone http repository' '
9497
test_cmp exp actual.smudged &&
9598
9699
grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
97-
test_line_count = 2 actual.gzip
100+
test_line_count = 2 actual.gzip &&
101+
102+
grep "Accept-Language: ko-KR, *" actual >actual.language &&
103+
test_line_count = 2 actual.language
98104
fi
99105
'
100106

0 commit comments

Comments
 (0)