mirror of
https://github.com/curl/curl.git
synced 2026-08-25 07:33:36 +03:00
http: expect 100 rework
Move all handling of HTTP's `Expect: 100-continue` feature into a client reader. Add sending flag `KEEP_SEND_TIMED` that triggers transfer sending on general events like a timer. HTTP installs a `CURL_CR_PROTOCOL` reader when announcing `Expect: 100-continue`. That reader works as follows: - on first invocation, records time, starts the `EXPIRE_100_TIMEOUT` timer, disables `KEEP_SEND`, enables `KEEP_SEND_TIMER` and returns 0, eos=FALSE like a paused upload. - on subsequent invocation it checks if the timer has expired. If so, it enables `KEEP_SEND` and switches to passing through reads to the underlying readers. Transfer handling's `readwrite()` will be invoked when a timer expires (like `EXPIRE_100_TIMEOUT`) or when data from the server arrives. Seeing `KEEP_SEND_TIMER`, it will try to upload more data, which triggers reading from the client readers again. Which then may lead to a new pausing or cause the upload to start. Flags and timestamps connected to this have been moved from `SingleRequest` into the reader's context. Closes #13110
This commit is contained in:
parent
3d0fd382a2
commit
80a3b830cc
17 changed files with 301 additions and 189 deletions
|
|
@ -46,6 +46,7 @@ class TestUpload:
|
|||
env.make_data_file(indir=env.gen_dir, fname="data-63k", fsize=63*1024)
|
||||
env.make_data_file(indir=env.gen_dir, fname="data-64k", fsize=64*1024)
|
||||
env.make_data_file(indir=env.gen_dir, fname="data-100k", fsize=100*1024)
|
||||
env.make_data_file(indir=env.gen_dir, fname="data-1m+", fsize=(1024*1024)+1)
|
||||
env.make_data_file(indir=env.gen_dir, fname="data-10m", fsize=10*1024*1024)
|
||||
httpd.clear_extra_configs()
|
||||
httpd.reload()
|
||||
|
|
@ -501,3 +502,29 @@ class TestUpload:
|
|||
up_speed = r.stats[0]['speed_upload']
|
||||
assert (speed_limit * 0.5) <= up_speed <= (speed_limit * 1.5), f'{r.stats[0]}'
|
||||
|
||||
# upload larger data, triggering "Expect: 100-continue" code paths
|
||||
@pytest.mark.parametrize("proto", ['http/1.1'])
|
||||
def test_07_60_upload_exp100(self, env: Env, httpd, nghttpx, repeat, proto):
|
||||
fdata = os.path.join(env.gen_dir, 'data-1m+')
|
||||
read_delay = 1
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-0]'\
|
||||
f'&read_delay={read_delay}s'
|
||||
r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto, extra_args=[
|
||||
'--expect100-timeout', f'{read_delay+1}'
|
||||
])
|
||||
r.check_stats(count=1, http_status=200, exitcode=0)
|
||||
|
||||
# upload larger data, triggering "Expect: 100-continue" code paths
|
||||
@pytest.mark.parametrize("proto", ['http/1.1'])
|
||||
def test_07_61_upload_exp100_timeout(self, env: Env, httpd, nghttpx, repeat, proto):
|
||||
fdata = os.path.join(env.gen_dir, 'data-1m+')
|
||||
read_delay = 2
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-0]'\
|
||||
f'&read_delay={read_delay}s'
|
||||
r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto, extra_args=[
|
||||
'--expect100-timeout', f'{read_delay-1}'
|
||||
])
|
||||
r.check_stats(count=1, http_status=200, exitcode=0)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue