]> granicus.if.org Git - curl/commitdiff
setopt: add CURLOPT_CURLU
authorJim Fuller <jim@webcomposite.com>
Thu, 1 Nov 2018 18:16:15 +0000 (19:16 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 9 Nov 2018 14:47:28 +0000 (15:47 +0100)
Allows an application to pass in a pre-parsed URL via a URL handle.

Closes #3227

16 files changed:
docs/examples/Makefile.inc
docs/examples/urlapi.c [new file with mode: 0644]
docs/libcurl/curl_easy_setopt.3
docs/libcurl/opts/CURLOPT_CURLU.3 [new file with mode: 0644]
docs/libcurl/opts/Makefile.inc
docs/libcurl/symbols-in-versions
include/curl/curl.h
include/curl/typecheck-gcc.h
lib/setopt.c
lib/transfer.c
lib/url.c
lib/urldata.h
tests/data/Makefile.inc
tests/data/test658 [new file with mode: 0644]
tests/libtest/Makefile.inc
tests/libtest/lib658.c [new file with mode: 0644]

index f51871f06a1c5006903ae1f1a6a0b0ceb4cdbee8..8dd55b9df75596e1bf4eb2f6e56c716953e75035 100644 (file)
@@ -34,7 +34,8 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
   imap-tls imap-multi url2file sftpget ftpsget postinmemory http2-download \
   http2-upload http2-serverpush getredirect ftpuploadfrommem               \
   ftpuploadresume sslbackend postit2-formadd multi-formadd                 \
-  shared-connection-cache sftpuploadresume http2-pushinmemory parseurl
+  shared-connection-cache sftpuploadresume http2-pushinmemory parseurl     \
+  urlapi
 
 # These examples require external dependencies that may not be commonly
 # available on POSIX systems, so don't bother attempting to compile them here.
diff --git a/docs/examples/urlapi.c b/docs/examples/urlapi.c
new file mode 100644 (file)
index 0000000..594f942
--- /dev/null
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Set working URL with CURLU *.
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+#if !CURL_AT_LEAST_VERSION(7, 62, 0)
+#error "this example requires curl 7.62.0 or later"
+#endif
+
+int main(void)
+{
+  CURL *curl;
+  CURLcode res;
+
+  CURLU *urlp;
+  CURLUcode uc;
+
+  /* get a curl handle */
+  curl = curl_easy_init();
+
+  /* init Curl URL */
+  urlp = curl_url();
+  uc = curl_url_set(urlp, CURLUPART_URL,
+                    "http://example.com/path/index.html", 0);
+
+  if(uc) {
+    fprintf(stderr, "curl_url_set() failed: %in", uc);
+    goto cleanup;
+  }
+
+  if(curl) {
+    /* set urlp to use as working URL */
+    curl_easy_setopt(curl, CURLOPT_CURLU, urlp);
+    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+    res = curl_easy_perform(curl);
+    /* Check for errors */
+    if(res != CURLE_OK)
+      fprintf(stderr, "curl_easy_perform() failed: %s\n",
+              curl_easy_strerror(res));
+
+    goto cleanup;
+  }
+
+  cleanup:
+  curl_url_cleanup(urlp);
+  curl_easy_cleanup(curl);
+  return 0;
+}
index bde52f999101d5d0fe82f0af0bfa840747d23708..f4b89c2f893f3184ba841b22624576b014e652b8 100644 (file)
@@ -407,6 +407,8 @@ Range requests. See \fICURLOPT_RANGE(3)\fP
 Resume a transfer. See \fICURLOPT_RESUME_FROM(3)\fP
 .IP CURLOPT_RESUME_FROM_LARGE
 Resume a transfer. See \fICURLOPT_RESUME_FROM_LARGE(3)\fP
+.IP CURLOPT_CURLU
+Set URL to work on with CURLU *. See \fICURLOPT_CURLU(3)\fP
 .IP CURLOPT_CUSTOMREQUEST
 Custom request/method. See \fICURLOPT_CUSTOMREQUEST(3)\fP
 .IP CURLOPT_FILETIME
diff --git a/docs/libcurl/opts/CURLOPT_CURLU.3 b/docs/libcurl/opts/CURLOPT_CURLU.3
new file mode 100644 (file)
index 0000000..5c762c9
--- /dev/null
@@ -0,0 +1,61 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_CURLU 3 "28 Oct 2018" "libcurl 7.63.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_CURLU \- set URL with CURLU *
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CURLU, void *pointer);
+.SH DESCRIPTION
+Pass in a pointer to the \fIURL\fP to work with. The parameter should be a
+CURLU *. Setting \fICURLOPT_CURLU(3)\fP will explicitly override \fICURLOPT_URL(3)\fP.
+
+.SH DEFAULT
+The default value of this parameter is NULL.
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *handle = curl_easy_init();
+CURLU *urlp = curl_url();
+int res = 0;
+if(curl) {
+
+  res = curl_url_set(urlp, CURLUPART_URL, "http://example.com", 0);
+
+  curl_easy_setopt(handle, CURLOPT_CURLU, urlp);
+
+  ret = curl_easy_perform(handle);
+
+  curl_url_cleanup(urlp);
+  curl_easy_cleanup(handle);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.63.0.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_URL "(3), "
+.BR curl_url "(3), " curl_url_get "(3), " curl_url_set "(3), "
index 117842dc39aa53450c5e7fcef1a544a597d73ad9..e58db5f4a744862bd4fa7f90cac35d21f972ac4d 100644 (file)
@@ -111,6 +111,7 @@ man_MANS =                                      \
   CURLOPT_CRLF.3                                \
   CURLOPT_CRLFILE.3                             \
   CURLOPT_CUSTOMREQUEST.3                       \
+  CURLOPT_CURLU.3                               \
   CURLOPT_DEBUGDATA.3                           \
   CURLOPT_DEBUGFUNCTION.3                       \
   CURLOPT_DEFAULT_PROTOCOL.3                    \
index 2ca08ea3fd57f782d87893158514c948288d56db..6c17c384c408bdf20ac40dd2730f498a74e71b40 100644 (file)
@@ -371,6 +371,7 @@ CURLOPT_COOKIESESSION           7.9.7
 CURLOPT_COPYPOSTFIELDS          7.17.1
 CURLOPT_CRLF                    7.1
 CURLOPT_CRLFILE                 7.19.0
+CURLOPT_CURLU                   7.63.0
 CURLOPT_CUSTOMREQUEST           7.1
 CURLOPT_DEBUGDATA               7.9.6
 CURLOPT_DEBUGFUNCTION           7.9.6
index 0b66f1462d9f2010740213a679ddf5e44d7873e7..5177e3571363d40064dd8972138f935d07fdf636 100644 (file)
@@ -1872,6 +1872,9 @@ typedef enum {
   /* Time in ms between connection upkeep calls for long-lived connections. */
   CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
 
+  /* Specify URL using CURL URL API. */
+  CINIT(CURLU, OBJECTPOINT, 282),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
index 244336204de4660df651afd8b7c384e2b32d3dba..01df7b15f9ab597793987609f9a8751fb236b0bc 100644 (file)
@@ -363,6 +363,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    (option) == CURLOPT_WRITEDATA ||                                           \
    (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
+   (option) == CURLOPT_CURLU ||                                               \
    0)
 
 /* evaluates to true if option takes a POST data argument (void* or char*) */
index 22956a20fbcfe328dc4e9357a9329b76fa59ae92..1627aba6dfdc12e1127c79806892104f7007fc7f 100644 (file)
@@ -1204,6 +1204,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.low_speed_time = arg;
     break;
+  case CURLOPT_CURLU:
+    /*
+     * pass CURLU to set URL
+     */
+    data->set.uh = va_arg(param, CURLU *);
+    break;
   case CURLOPT_URL:
     /*
      * The URL to fetch.
index de6043d7d340226493ef1fb7fc9d9569afa8c0f6..32ca5a4963a7713198e1ddaf6e46a2e812018d50 100644 (file)
@@ -1353,17 +1353,30 @@ void Curl_init_CONNECT(struct Curl_easy *data)
 CURLcode Curl_pretransfer(struct Curl_easy *data)
 {
   CURLcode result;
-  if(!data->change.url) {
+
+  if(!data->change.url && !data->set.uh) {
     /* we can't do anything without URL */
     failf(data, "No URL set!");
     return CURLE_URL_MALFORMAT;
   }
+
   /* since the URL may have been redirected in a previous use of this handle */
   if(data->change.url_alloc) {
     /* the already set URL is allocated, free it first! */
     Curl_safefree(data->change.url);
     data->change.url_alloc = FALSE;
   }
+
+  if(!data->change.url && data->set.uh) {
+    CURLUcode uc;
+    uc = curl_url_get(data->set.uh,
+                        CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
+    if(uc) {
+      failf(data, "No URL set!");
+      return CURLE_URL_MALFORMAT;
+    }
+  }
+
   data->change.url = data->set.str[STRING_SET_URL];
 
   /* Init the SSL session ID cache here. We do it here since we want to do it
index dd9fa2617f73e607260e65cdb8f9326edc0b803a..6118177d697ba3083ecaa04153425868d53be912 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -2026,7 +2026,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   Curl_up_free(data); /* cleanup previous leftovers first */
 
   /* parse the URL */
-  uh = data->state.uh = curl_url();
+  if(data->set.uh) {
+    uh = data->set.uh;
+  }
+  else {
+    uh = data->state.uh = curl_url();
+  }
+
   if(!uh)
     return CURLE_OUT_OF_MEMORY;
 
@@ -2043,15 +2049,17 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     data->change.url_alloc = TRUE;
   }
 
-  uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+  if(!data->set.uh) {
+    uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
                     CURLU_GUESS_SCHEME |
                     CURLU_NON_SUPPORT_SCHEME |
                     (data->set.disallow_username_in_url ?
                      CURLU_DISALLOW_USER : 0) |
                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
-  if(uc) {
-    DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
-    return Curl_uc_to_curlcode(uc);
+    if(uc) {
+      DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
+      return Curl_uc_to_curlcode(uc);
+  }
   }
 
   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
@@ -2193,6 +2201,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+
 /*
  * If we're doing a resumed transfer, we need to setup our stuff
  * properly.
index 11a6a22c616f605f13800a6fd838d6f805835258..eae73a19f3bc8dc4429d4a446ced018abdef7ffc 100644 (file)
@@ -1728,6 +1728,7 @@ struct UserDefined {
   bool doh_get; /* use GET for DoH requests, instead of POST */
   multidone_func fmultidone;
   struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
+  CURLU *uh; /* URL handle for the current parsed URL */
 };
 
 struct Names {
index 669a482dede0f28bed3abdf0e6f14f62c8761f46..e58fb27fbfc96e2b4acb25ded5e0dafa68d88a6c 100644 (file)
@@ -83,7 +83,7 @@ test617 test618 test619 test620 test621 test622 test623 test624 test625 \
 test626 test627 test628 test629 test630 test631 test632 test633 test634 \
 test635 test636 test637 test638 test639 test640 test641 test642 \
 test643 test644 test645 test646 test647 test648 test649 test650 test651 \
-test652 test653 test654 test655 test656 \
+test652 test653 test654 test655 test656 test658 \
 \
 test700 test701 test702 test703 test704 test705 test706 test707 test708 \
 test709 test710 test711 test712 test713 test714 test715 \
diff --git a/tests/data/test658 b/tests/data/test658
new file mode 100644 (file)
index 0000000..c75293c
--- /dev/null
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+<client>
+<server>
+http
+</server>
+<tool>
+lib658
+</tool>
+<name>
+HTTP GET
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/658
+</command>
+</client>
+
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /658 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+\r
+</verify>
+
+</testcase>
index 7a3cd166598d05e787a0b41e52835f0d793a0c03..6dc7511f1f36ae532ba65a3c30b3c8dd93ffbf35 100644 (file)
@@ -21,7 +21,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect                \
  lib559 lib560 lib562 lib564 lib565 lib566 lib567 lib568 lib569 lib570   \
  lib571 lib572 lib573 lib574 lib575 lib576        lib578 lib579 lib582   \
  lib583 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598 lib599   \
- lib643 lib644 lib645 lib650 lib651 lib652 lib653 lib654 lib655 \
+ lib643 lib644 lib645 lib650 lib651 lib652 lib653 lib654 lib655 lib658   \
  lib1156 \
  lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
  lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515         lib1517 \
@@ -339,6 +339,10 @@ lib654_CPPFLAGS = $(AM_CPPFLAGS)
 lib655_SOURCES = lib655.c $(SUPPORTFILES)
 lib655_CPPFLAGS = $(AM_CPPFLAGS)
 
+lib658_SOURCES = lib658.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib658_LDADD = $(TESTUTIL_LIBS)
+lib658_CPPFLAGS = $(AM_CPPFLAGS)
+
 lib1500_SOURCES = lib1500.c $(SUPPORTFILES) $(TESTUTIL)
 lib1500_LDADD = $(TESTUTIL_LIBS)
 lib1500_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/libtest/lib658.c b/tests/libtest/lib658.c
new file mode 100644 (file)
index 0000000..98e0db4
--- /dev/null
@@ -0,0 +1,76 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+/*
+ * Get a single URL without select().
+ */
+
+int test(char *URL)
+{
+  CURL *handle = NULL;
+  CURLcode res = 0;
+  CURLU *urlp = NULL;
+  CURLUcode uc = 0;
+
+  global_init(CURL_GLOBAL_ALL);
+  easy_init(handle);
+
+  urlp = curl_url();
+
+  if(!urlp) {
+    fprintf(stderr, "problem init URL api.");
+    goto test_cleanup;
+  }
+
+  uc = curl_url_set(urlp, CURLUPART_URL, URL, 0);
+  if(uc) {
+    fprintf(stderr, "problem setting CURLUPART_URL.");
+    goto test_cleanup;
+  }
+
+  /* demonstrate override behavior */
+  easy_setopt(handle, CURLOPT_URL, "http://www.example.com");
+
+  easy_setopt(handle, CURLOPT_CURLU, urlp);
+  easy_setopt(handle, CURLOPT_VERBOSE, 1L);
+
+  res = curl_easy_perform(handle);
+
+  if(res) {
+    fprintf(stderr, "%s:%d curl_easy_perform() failed with code %d (%s)\n",
+            __FILE__, __LINE__, res, curl_easy_strerror(res));
+    goto test_cleanup;
+  }
+
+test_cleanup:
+
+  curl_url_cleanup(urlp);
+  curl_easy_cleanup(handle);
+  curl_global_cleanup();
+
+  return res;
+}