Skip to content

Using CURLOPT_CURLU with CURLOPT_PORT overwrites port from url... #3753

Closed
@ptlomholt

Description

@ptlomholt

I'm using the new CURLOPT_CURLU feature to take advantage of curl's 'accumulative', relative url capabilities, but it appears that when also using CURLOPT_PORT, curl overwrites the port portion of the url in 'my' CURLU handle set by CURLOPT_CURLU. If I later use CURLOPT_PORT passing 0L to go back to the original port, curl instead remembers the port set by the previous CURLOPT_PORT call!

This behavior is different from using the classic 'CURLOPT_URL' way of passing the url to curl, where it correctly reverts back to the port indicated in the orginal url.

I figure the problem has to do with the way curl treats its internal CURLU handle as a 'scratch' area which is fine when used with a CURLOPT_URL url, which, I assume, resets the CURLU handle before every new transaction, but with CURLOPT_CURLU it clashes with 'my' CURLU handle, which I expect curl should leave alone and treat as read-only.

The following code illustrates the problem :

#include "curl/curl.h"
#include <stdio.h>

static char error_buffer[CURL_ERROR_SIZE] = "";

int main(void)
{
    const char *url = "http://httpbin.org/get";
    char *url_after;
    CURLU *curlu = curl_url();
    CURL *curl = curl_easy_init();
    CURLcode curl_code;

    printf("using curl version %s\n", curl_version_info(CURLVERSION_NOW)->version);

    curl_url_set(curlu, CURLUPART_URL, url, CURLU_DEFAULT_SCHEME);
    curl_easy_setopt(curl, CURLOPT_CURLU, curlu);
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl, CURLOPT_PORT, 1234L); // should not work, that's ok
    curl_code = curl_easy_perform(curl);
    printf("failure expected, curl_easy_perform returned %ld: <%s>, <%s>\n",
                                   (long) curl_code, curl_easy_strerror(curl_code), error_buffer);

    // print url
    curl_url_get(curlu, CURLUPART_URL, &url_after, 0);
    printf("curlu now: <%s>\n", url_after);
    curl_free(url_after);

    // now reset port to go back to port 80 (not!)
    curl_easy_setopt(curl, CURLOPT_PORT, 0L);

    curl_code = curl_easy_perform(curl);
    printf("success expected, curl_easy_perform returned %ld: <%s>, <%s>\n", 
                                   (long) curl_code, curl_easy_strerror(curl_code), error_buffer);

    // print url
    curl_url_get(curlu, CURLUPART_URL, &url_after, 0);
    printf("curlu now: <%s>\n", url_after);
    curl_free(url_after);

    curl_easy_cleanup(curl);
    curl_url_cleanup(curlu);

    return 0;
}

It generates the following output, note how it appears stuck on port 1234:

using curl version 7.65.0-DEV
*   Trying 52.71.234.219...
* TCP_NODELAY set
* connect to 52.71.234.219 port 1234 failed: Connection refused
*   Trying 3.85.154.144...
* TCP_NODELAY set
* connect to 3.85.154.144 port 1234 failed: Connection refused
* Failed to connect to httpbin.org port 1234: Connection refused
* Closing connection 0
failure expected, curl_easy_perform returned 7: <Couldn't connect to
server>, <Failed to connect to httpbin.org port 1234: Connection refused>
curlu now: <http://httpbin.org:1234/get>
* Hostname httpbin.org was found in DNS cache
*   Trying 52.71.234.219...
* TCP_NODELAY set
* connect to 52.71.234.219 port 1234 failed: Connection refused
*   Trying 3.85.154.144...
* TCP_NODELAY set
* connect to 3.85.154.144 port 1234 failed: Connection refused
* Failed to connect to httpbin.org port 1234: Connection refused
* Closing connection 1
success expected, curl_easy_perform returned 7: <Couldn't connect to
server>, <Failed to connect to httpbin.org port 1234: Connection refused>
curlu now: <http://httpbin.org:1234/get>

curl/libcurl version

7.64.1 and 7.65.0-DEV (github master (as of April 8th 2019))

operating system

CentOS 7, but probably not OS specific

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions