blob: dabcef0565769b9fb18054ac3db96fae446c52d4 [file] [log] [blame]
xf.li6c8fc1e2023-08-12 00:11:09 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24/* <DESC>
25 * Issue an HTTP POST and provide the data through the read callback.
26 * </DESC>
27 */
28#include <stdio.h>
29#include <string.h>
30#include <curl/curl.h>
31
32/* silly test data to POST */
33static const char data[]="Lorem ipsum dolor sit amet, consectetur adipiscing "
34 "elit. Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at "
35 "laoreet rhoncus, odio ipsum semper metus, at tempus ante urna in mauris. "
36 "Suspendisse ornare tempor venenatis. Ut dui neque, pellentesque a varius "
37 "eget, mattis vitae ligula. Fusce ut pharetra est. Ut ullamcorper mi ac "
38 "sollicitudin semper. Praesent sit amet tellus varius, posuere nulla non, "
39 "rhoncus ipsum.";
40
41struct WriteThis {
42 const char *readptr;
43 size_t sizeleft;
44};
45
46static size_t read_callback(char *dest, size_t size, size_t nmemb, void *userp)
47{
48 struct WriteThis *wt = (struct WriteThis *)userp;
49 size_t buffer_size = size*nmemb;
50
51 if(wt->sizeleft) {
52 /* copy as much as possible from the source to the destination */
53 size_t copy_this_much = wt->sizeleft;
54 if(copy_this_much > buffer_size)
55 copy_this_much = buffer_size;
56 memcpy(dest, wt->readptr, copy_this_much);
57
58 wt->readptr += copy_this_much;
59 wt->sizeleft -= copy_this_much;
60 return copy_this_much; /* we copied this many bytes */
61 }
62
63 return 0; /* no more data left to deliver */
64}
65
66int main(void)
67{
68 CURL *curl;
69 CURLcode res;
70
71 struct WriteThis wt;
72
73 wt.readptr = data;
74 wt.sizeleft = strlen(data);
75
76 /* In windows, this will init the winsock stuff */
77 res = curl_global_init(CURL_GLOBAL_DEFAULT);
78 /* Check for errors */
79 if(res != CURLE_OK) {
80 fprintf(stderr, "curl_global_init() failed: %s\n",
81 curl_easy_strerror(res));
82 return 1;
83 }
84
85 /* get a curl handle */
86 curl = curl_easy_init();
87 if(curl) {
88 /* First set the URL that is about to receive our POST. */
89 curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/index.cgi");
90
91 /* Now specify we want to POST data */
92 curl_easy_setopt(curl, CURLOPT_POST, 1L);
93
94 /* we want to use our own read function */
95 curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
96
97 /* pointer to pass to our read function */
98 curl_easy_setopt(curl, CURLOPT_READDATA, &wt);
99
100 /* get verbose debug output please */
101 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
102
103 /*
104 If you use POST to a HTTP 1.1 server, you can send data without knowing
105 the size before starting the POST if you use chunked encoding. You
106 enable this by adding a header like "Transfer-Encoding: chunked" with
107 CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you must
108 specify the size in the request.
109 */
110#ifdef USE_CHUNKED
111 {
112 struct curl_slist *chunk = NULL;
113
114 chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked");
115 res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
116 /* use curl_slist_free_all() after the *perform() call to free this
117 list again */
118 }
119#else
120 /* Set the expected POST size. If you want to POST large amounts of data,
121 consider CURLOPT_POSTFIELDSIZE_LARGE */
122 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)wt.sizeleft);
123#endif
124
125#ifdef DISABLE_EXPECT
126 /*
127 Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue"
128 header. You can disable this header with CURLOPT_HTTPHEADER as usual.
129 NOTE: if you want chunked transfer too, you need to combine these two
130 since you can only set one list of headers with CURLOPT_HTTPHEADER. */
131
132 /* A less good option would be to enforce HTTP 1.0, but that might also
133 have other implications. */
134 {
135 struct curl_slist *chunk = NULL;
136
137 chunk = curl_slist_append(chunk, "Expect:");
138 res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
139 /* use curl_slist_free_all() after the *perform() call to free this
140 list again */
141 }
142#endif
143
144 /* Perform the request, res will get the return code */
145 res = curl_easy_perform(curl);
146 /* Check for errors */
147 if(res != CURLE_OK)
148 fprintf(stderr, "curl_easy_perform() failed: %s\n",
149 curl_easy_strerror(res));
150
151 /* always cleanup */
152 curl_easy_cleanup(curl);
153 }
154 curl_global_cleanup();
155 return 0;
156}