1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "http_client.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
28 #include <curl/curl.h>
35 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp);
37 int http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data) {
41 const char *send_data_good = send_data;
46 CURL *curl = curl_easy_init();
48 log_error("could not initialize cURL\n");
49 return NTS_ERR_FAILED;
53 struct curl_slist *header = 0;
54 header = curl_slist_append(header, "Content-Type: application/json");
56 log_error("curl_slist_append failed\n");
57 curl_easy_cleanup(curl);
58 return NTS_ERR_FAILED;
61 header = curl_slist_append(header, "Accept: application/json");
63 log_error("curl_slist_append failed\n");
64 curl_easy_cleanup(curl);
65 return NTS_ERR_FAILED;
68 int curl_connect_timeout = get_int_from_string_with_default(getenv("CURL_CONNECT_TIMEOUT"), 1);
69 int curl_operation_timeout = get_int_from_string_with_default(getenv("CURL_OPERATION_TIMEOUT"), 1);
71 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
72 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, (long)curl_connect_timeout); //seconds timeout for a connection
73 curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)curl_operation_timeout); //seconds timeout for an operation
74 curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, (long)curl_connect_timeout);
75 curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
77 // disable SSL verifications
78 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
79 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
80 curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
81 curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
83 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
84 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
85 curl_easy_setopt(curl, CURLOPT_URL, url);
87 if((username) && (password)) {
88 char *credentials = 0;
89 asprintf(&credentials, "%s:%s", username, password);
90 if(credentials == 0) {
91 log_error("asprintf failed\n");
92 curl_slist_free_all(header);
93 curl_easy_cleanup(curl);
94 return NTS_ERR_FAILED;
96 curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
100 struct memory response_data = {0};
102 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
103 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
106 log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"... ", method, url, send_data_good);
107 CURLcode res = curl_easy_perform(curl);
108 curl_slist_free_all(header);
110 if(res != CURLE_OK) {
111 log_add(2, "failed with error: %s\n", curl_easy_strerror(res));
112 curl_easy_cleanup(curl);
113 return NTS_ERR_FAILED;
116 log_add(2, "success\n");
121 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
122 *response_code = http_rc;
126 *recv_data = response_data.response;
129 curl_easy_cleanup(curl);
133 int http_socket_request(const char *url, const char *sock_fname, const char *method, const char *send_data, int *response_code, char **recv_data) {
138 const char *send_data_good = send_data;
139 if(!send_data_good) {
143 CURL *curl = curl_easy_init();
145 log_error("could not initialize cURL\n");
146 return NTS_ERR_FAILED;
150 struct curl_slist *header = 0;
151 header = curl_slist_append(header, "Content-Type: application/json");
153 log_error("curl_slist_append failed\n");
154 curl_easy_cleanup(curl);
155 return NTS_ERR_FAILED;
158 header = curl_slist_append(header, "Accept: application/json");
160 log_error("curl_slist_append failed\n");
161 curl_easy_cleanup(curl);
162 return NTS_ERR_FAILED;
165 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
166 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); //seconds timeout for a connection
167 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); //seconds timeout for an operation
168 curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
169 curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
171 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
172 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
173 curl_easy_setopt(curl, CURLOPT_URL, url);
174 curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, sock_fname);
176 struct memory response_data = {0};
178 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
179 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
182 log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good);
183 CURLcode res = curl_easy_perform(curl);
184 curl_slist_free_all(header);
186 if(res != CURLE_OK) {
187 log_add(2, "failed with error %s\n", curl_easy_strerror(res));
188 curl_easy_cleanup(curl);
189 return NTS_ERR_FAILED;
192 log_add(2, "success\n");
197 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
198 *response_code = http_rc;
202 *recv_data = response_data.response;
205 curl_easy_cleanup(curl);
209 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
210 size_t realsize = size * nmemb;
211 struct memory *mem = (struct memory *)userp;
213 char *ptr = realloc(mem->response, mem->size + realsize + 1);
215 log_error("realloc failed\n");
216 return 0; /* out of memory! */
220 memcpy(&(mem->response[mem->size]), data, realsize);
221 mem->size += realsize;
222 mem->response[mem->size] = 0;