mirror of
https://github.com/curl/curl.git
synced 2026-08-03 17:50:28 +03:00
http2: improved upload eos handling
- replace the counting of upload lengths with the new eos send flag - improve frequency of stream draining to happen less on events where it is not needed - this PR is based on #14220 http2, cf-h2-proxy: fix EAGAINed out buffer - in adjust pollset and shutdown handling, a non-empty `ctx->outbufq` must trigger send polling, irregardless of http/2 flow control - in http2, fix retry handling of blocked GOAWAY frame test case improvement: - let client 'upload-pausing' handle http versions Closes #14253
This commit is contained in:
parent
344ba8c883
commit
35bf766280
10 changed files with 302 additions and 190 deletions
|
|
@ -182,7 +182,16 @@ static int err(void)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
static void usage(const char *msg)
|
||||
{
|
||||
if(msg)
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
fprintf(stderr,
|
||||
"usage: [options] url\n"
|
||||
" upload and pause, options:\n"
|
||||
" -V http_version (http/1.1, h2, h3) http version to use\n"
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
|
@ -192,12 +201,37 @@ int main(int argc, char *argv[])
|
|||
struct curl_slist *resolve = NULL;
|
||||
char resolve_buf[1024];
|
||||
char *url, *host = NULL, *port = NULL;
|
||||
int http_version = CURL_HTTP_VERSION_1_1;
|
||||
int ch;
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr, "ERROR: need URL as argument\n");
|
||||
while((ch = getopt(argc, argv, "V:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'V': {
|
||||
if(!strcmp("http/1.1", optarg))
|
||||
http_version = CURL_HTTP_VERSION_1_1;
|
||||
else if(!strcmp("h2", optarg))
|
||||
http_version = CURL_HTTP_VERSION_2_0;
|
||||
else if(!strcmp("h3", optarg))
|
||||
http_version = CURL_HTTP_VERSION_3ONLY;
|
||||
else {
|
||||
usage("invalid http version");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
usage("invalid option");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc != 1) {
|
||||
usage("not enough arguments");
|
||||
return 2;
|
||||
}
|
||||
url = argv[1];
|
||||
url = argv[0];
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl_global_trace("ids,time");
|
||||
|
|
@ -247,6 +281,9 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
|
||||
if(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_cb)
|
||||
!= CURLE_OK ||
|
||||
|
|
@ -254,6 +291,8 @@ int main(int argc, char *argv[])
|
|||
err();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, http_version);
|
||||
|
||||
rc = curl_easy_perform(curl);
|
||||
|
||||
if(curl) {
|
||||
|
|
|
|||
|
|
@ -475,9 +475,14 @@ class TestUpload:
|
|||
client = LocalClient(name='upload-pausing', env=env, timeout=60)
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
url = f'http://{env.domain1}:{env.http_port}/curltest/echo?id=[0-0]&die_after=0'
|
||||
r = client.run([url])
|
||||
r.check_exit_code(18) # PARTIAL_FILE
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]&die_after=0'
|
||||
r = client.run(['-V', proto, url])
|
||||
exp_code = 18 # PARTIAL_FILE
|
||||
if proto == 'h2':
|
||||
exp_code = 92 # CURLE_HTTP2_STREAM
|
||||
elif proto == 'h3':
|
||||
exp_code = 95 # CURLE_HTTP3
|
||||
r.check_exit_code(exp_code)
|
||||
|
||||
# upload data, pause, let connection die without any response at all
|
||||
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
|
||||
|
|
@ -489,9 +494,12 @@ class TestUpload:
|
|||
client = LocalClient(name='upload-pausing', env=env, timeout=60)
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
url = f'http://{env.domain1}:{env.http_port}/curltest/echo?id=[0-0]&just_die=1'
|
||||
r = client.run([url])
|
||||
r.check_exit_code(52) # GOT_NOTHING
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]&just_die=1'
|
||||
r = client.run(['-V', proto, url])
|
||||
exp_code = 52 # GOT_NOTHING
|
||||
if proto == 'h2' or proto == 'h3':
|
||||
exp_code = 0 # we get a 500 from the server
|
||||
r.check_exit_code(exp_code) # GOT_NOTHING
|
||||
|
||||
# upload data, pause, let connection die after 100 continue
|
||||
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
|
||||
|
|
@ -503,9 +511,12 @@ class TestUpload:
|
|||
client = LocalClient(name='upload-pausing', env=env, timeout=60)
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
url = f'http://{env.domain1}:{env.http_port}/curltest/echo?id=[0-0]&die_after_100=1'
|
||||
r = client.run([url])
|
||||
r.check_exit_code(52) # GOT_NOTHING
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]&die_after_100=1'
|
||||
r = client.run(['-V', proto, url])
|
||||
exp_code = 52 # GOT_NOTHING
|
||||
if proto == 'h2' or proto == 'h3':
|
||||
exp_code = 0 # we get a 500 from the server
|
||||
r.check_exit_code(exp_code) # GOT_NOTHING
|
||||
|
||||
# speed limited on put handler
|
||||
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ class TestProxy:
|
|||
indata = open(srcfile).readlines()
|
||||
for i in range(count):
|
||||
respdata = open(curl.response_file(i)).readlines()
|
||||
assert respdata == indata
|
||||
assert respdata == indata, f'resonse {i} differs'
|
||||
assert r.total_connects == 1, r.dump_logs()
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue