return CURLE_RECV_ERROR;
}
}
- if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
- drain_stream(cf, data, stream);
- }
break;
case NGHTTP2_HEADERS:
if(stream->bodystarted) {
return CURLE_RECV_ERROR;
/* Only final status code signals the end of header */
- if(stream->status_code / 100 != 1) {
+ if(stream->status_code / 100 != 1)
stream->bodystarted = TRUE;
+ else
stream->status_code = -1;
- }
h2_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed);
default:
break;
}
+
+ if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ if(!stream->closed && !stream->body_eos &&
+ ((stream->status_code >= 400) || (stream->status_code < 200))) {
+ /* The server did not give us a positive response and we are not
+ * done uploading the request body. We need to stop doing that and
+ * also inform the server that we aborted our side. */
+ CURL_TRC_CF(data, cf, "[%d] EOS frame with unfinished upload and "
+ "HTTP status %d, abort upload by RST",
+ stream_id, stream->status_code);
+ nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
+ stream->id, NGHTTP2_STREAM_CLOSED);
+ stream->closed = TRUE;
+ }
+ drain_stream(cf, data, stream);
+ }
return CURLE_OK;
}
exp_code = 0 # we get a 500 from the server
r.check_exit_code(exp_code) # GOT_NOTHING
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_43_upload_denied(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ count = 1
+ max_upload = 128 * 1024
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?'\
+ f'id=[0-{count-1}]&max_upload={max_upload}'
+ r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto,
+ extra_args=['--trace-config', 'all'])
+ r.check_stats(count=count, http_status=413, exitcode=0)
+
# speed limited on put handler
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_07_50_put_speed_limit(self, env: Env, httpd, nghttpx, proto, repeat):
char buffer[128*1024];
const char *ct;
apr_off_t rbody_len = 0;
+ apr_off_t rbody_max_len = -1;
const char *s_rbody_len;
const char *request_id = "none";
apr_time_t read_delay = 0, chunk_delay = 0;
continue;
}
}
+ else if(!strcmp("max_upload", arg)) {
+ rbody_max_len = (int)apr_atoi64(val);
+ continue;
+ }
}
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "query parameter not "
"understood: '%s' in %s",
apr_sleep(chunk_delay);
}
rbody_len += l;
+ if((rbody_max_len > 0) && (rbody_len > rbody_max_len)) {
+ r->status = 413;
+ break;
+ }
}
}
/* we are done */
rv = ap_pass_brigade(r->output_filters, bb);
+ if(r->status == 413) {
+ apr_sleep(apr_time_from_sec(1));
+ }
+
cleanup:
if(rv == APR_SUCCESS
|| r->status != HTTP_OK