Skip to content

curl_easy_perform() waits full response with CURLOPT_CONNECT_ONLY enabled #17621

@KirillObukhov

Description

@KirillObukhov

I did this

I'm trying to receive Server-Sent Events using libcurl. I've found CURLOPT_CONNECT_ONLY option which

can be set to '2' and if HTTP or WebSocket are used, libcurl performs the request and reads all response headers before handing over control to the application

but curl_easy_perform() call blocks while connection alive.

For demonstration, I have attached a simple server and client applications.
demo.zip

The server (Kotlin) sends 5 messages every 3 seconds and terminates the connection.

           sse {
                repeat(5) {
                    delay(3.seconds)
                    send(LocalTime.now().toString())
                }
            }

The client (C) connects to the server, exchange HTTP headers, report the execution time and should exit without waiting events.

  CURL *curl = curl_easy_init();
  if (!curl)
    goto cleanup;
  if (curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8080"))
    goto cleanup;
  if (curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L))
    goto cleanup;

  time_t start_time = time(NULL);
  if (curl_easy_perform(curl))
    goto cleanup;
  time_t end_time = time(NULL);

  double duration = difftime(end_time, start_time);
  printf("perform takes %.2f seconds\n", duration);

but outputs

perform takes 15.00 seconds

How-to build & run server:

cd server
gradle build
cd build/distributions
tar -xf server.tar
./server/bin/server

curl -v http://localhost:8080

* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
* using HTTP/1.x
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.12.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Content-Type: text/event-stream
< Cache-Control: no-store
< Connection: keep-alive
< X-Accel-Buffering: no
< Transfer-Encoding: chunked
< 
data: 22:22:18.489580323

data: 22:22:21.490710433

data: 22:22:24.491684059

data: 22:22:27.492930039

data: 22:22:30.494157034

* Connection #0 to host localhost left intact

I expected the following

No response

curl/libcurl version

curl 8.12.1 (x86_64-pc-linux-gnu) libcurl/8.12.1 OpenSSL/3.4.1 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 libidn2/2.3.8 libpsl/0.21.2 libssh2/1.11.1 nghttp2/1.64.0 librtmp/2.3 OpenLDAP/2.6.9
Release-Date: 2025-02-13, security patched: 8.12.1-3ubuntu1
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

operating system

Linux lpc 6.14.0-15-generic #15-Ubuntu SMP PREEMPT_DYNAMIC Sun Apr 6 15:05:05 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions