Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/2 + CURLOPT_FAILONERROR returns incorrect error code CURLE_RECV_ERROR #13411

laramiel opened this issue Apr 18, 2024 · 2 comments


Copy link

laramiel commented Apr 18, 2024

I did this

Created an http/2 request to a missing URL (404) with the following options:

curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, true)

See expected outcome.

CURLE_HTTP_RETURNED_ERROR is returned in ~2 places in http.c, which participates in this call
stack when processed via curl_easy_perform:

in http2.c, on_frame_recv, the error code lost via a conversion to NGHTTP2_ERR_CALLBACK_FAILURE

This propagates out to h2_process_pending_input which then emits CURLE_RECV_ERROR

The relevant call stack is:

http_on_response (curl/src/lib/http.c:3531)   <--- return CURLE_HTTP_RETURNED_ERROR
http_rw_headers (curl/src/lib/http.c:3779)
Curl_http_write_resp_hds (curl/src/lib/http.c:3963)
Curl_http_write_resp (curl/src/lib/http.c:3990)
Curl_xfer_write_resp (curl/src/lib/transfer.c:1166)
recvbuf_write_hds (curl/src/lib/http2.c:953)
on_stream_frame (curl/src/lib/http2.c:1011)
on_frame_recv (curl/src/lib/http2.c:1221)   <--- return NGHTTP2_ERR_CALLBACK_FAILURE
session_call_on_frame_received (nghttp2/src/lib/nghttp2_session.c:3651)
session_after_header_block_received (nghttp2/src/lib/nghttp2_session.c:4173)
nghttp2_session_mem_recv2 (nghttp2/src/lib/nghttp2_session.c:6828)
nghttp2_session_mem_recv (nghttp2/src/lib/nghttp2_session.c:5859)
h2_process_pending_input (curl/src/lib/http2.c:539)   <--- return CURLE_RECV_ERROR
h2_progress_ingress (curl/src/lib/http2.c:1872)
cf_h2_recv (curl/src/lib/http2.c:1911)
Curl_cf_def_recv (curl/src/lib/cfilters.c:103)
Curl_cf_recv (curl/src/lib/cfilters.c:184)
Curl_conn_recv (curl/src/lib/cfilters.c:688)
Curl_xfer_recv (curl/src/lib/transfer.c:1246)
Curl_xfer_recv_resp (curl/src/lib/transfer.c:197)
readwrite_data (curl/src/lib/transfer.c:253)
Curl_readwrite (curl/src/lib/transfer.c:460)
multi_runsingle (curl/src/lib/multi.c:2407)
curl_multi_perform (curl/src/lib/multi.c:2704)
easy_transfer (curl/src/lib/easy.c:676)
easy_perform (curl/src/lib/easy.c:768)
curl_easy_perform (curl/src/lib/easy.c:787)

I expected the following

Actual error code CURLE_RECV_ERROR

Expected the error code CURLE_HTTP_RETURNED_ERROR

curl/libcurl version

curl 8.7.1+

operating system

Debian 6.6.13-1rodete3 (2024-03-04) x86_64 GNU/Linux

Built from source.

@bagder bagder added the HTTP/2 label Apr 18, 2024
Copy link

bagder commented Apr 18, 2024

Confirmed for me as well on git master:

One way to reproduce:

curl -f -I

compared to the same using HTTP/1:

curl --http1.1 -f -I

bagder added a commit that referenced this issue Apr 18, 2024
When the nghttp2 callback on_frame_recv() returns error, we now set an
extra "real" return code to pass that value back to return.

This avoids all callback errors sloppily get reported as
CURLE_RECV_ERROR. For example for 4xx responses when CURLOPT_FAILONERROR
is set.

Reported-by: Laramie Leavitt
Fixes #13411
icing added a commit to icing/curl that referenced this issue Apr 19, 2024
- refs curl#13411
- errors returned by Curl_xfer_write_resp() and the header variant
  are not errors in the protocol. The result needs to be returned
  on the next recv() from the protocol filter.
- make xfer write errors for response data cause the stream to
  be cancelled
- added pytest test_02_14 and test_02_15 to verify that also for
  parallel processing
@icing icing self-assigned this Apr 19, 2024
Copy link

icing commented Apr 19, 2024

Proposing a fix for this in #13424.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Successfully merging a pull request may close this issue.

3 participants