CI: Update RTD configuration file
[sim/o1-interface.git] / ntsimulator / ntsim-ng / utils / http_client.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
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
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
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 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "http_client.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include <curl/curl.h>
29
30 struct memory {
31     char *response;
32     size_t size;
33 };
34
35 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp);
36
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) {
38     assert(url);
39     assert(method);
40
41     const char *send_data_good = send_data;
42     if(!send_data_good) {
43         send_data_good = "";
44     }
45
46     CURL *curl = curl_easy_init();
47     if(curl == 0) {
48         log_error("could not initialize cURL\n");
49         return NTS_ERR_FAILED;
50     }
51
52     // set curl options
53     struct curl_slist *header = 0;
54     header = curl_slist_append(header, "Content-Type: application/json");
55     if(!header) {
56         log_error("curl_slist_append failed\n");
57         curl_easy_cleanup(curl);
58         return NTS_ERR_FAILED;
59     }
60
61     header = curl_slist_append(header, "Accept: application/json");
62     if(!header) {
63         log_error("curl_slist_append failed\n");
64         curl_easy_cleanup(curl);
65         return NTS_ERR_FAILED;
66     }
67
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);
70
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);
76
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);
82
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);
86
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;
95         }
96         curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
97         free(credentials);
98     }
99
100     struct memory response_data = {0};
101     if(recv_data) {
102         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
103         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
104     }
105
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);
109
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;
114     }
115     else {
116         log_add(2, "success\n");
117     }
118
119     if(response_code) {
120         long http_rc;
121         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
122         *response_code = http_rc;
123     }
124
125     if(recv_data) {
126         *recv_data = response_data.response;
127     }
128
129     curl_easy_cleanup(curl);
130     return NTS_ERR_OK;
131 }
132
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) {
134     assert(url);
135     assert(sock_fname);
136     assert(method);
137
138     const char *send_data_good = send_data;
139     if(!send_data_good) {
140         send_data_good = "";
141     }
142
143     CURL *curl = curl_easy_init();
144     if(curl == 0) {
145         log_error("could not initialize cURL\n");
146         return NTS_ERR_FAILED;
147     }
148
149     // set curl options
150     struct curl_slist *header = 0;
151     header = curl_slist_append(header, "Content-Type: application/json");
152     if(!header) {
153         log_error("curl_slist_append failed\n");
154         curl_easy_cleanup(curl);
155         return NTS_ERR_FAILED;
156     }
157
158     header = curl_slist_append(header, "Accept: application/json");
159     if(!header) {
160         log_error("curl_slist_append failed\n");
161         curl_easy_cleanup(curl);
162         return NTS_ERR_FAILED;
163     }
164
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);
170
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);
175
176     struct memory response_data = {0};
177     if(recv_data) {
178         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
179         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
180     }
181
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);
185
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;
190     }
191     else {
192         log_add(2, "success\n");
193     }
194
195     if(response_code) {
196         long http_rc;
197         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
198         *response_code = http_rc;
199     }
200
201     if(recv_data) {
202         *recv_data = response_data.response;
203     }
204
205     curl_easy_cleanup(curl);
206     return NTS_ERR_OK;
207 }
208
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;
212
213     char *ptr = realloc(mem->response, mem->size + realsize + 1);
214     if(ptr == NULL) {
215         log_error("realloc failed\n");
216         return 0;  /* out of memory! */
217     }
218
219     mem->response = ptr;
220     memcpy(&(mem->response[mem->size]), data, realsize);
221     mem->size += realsize;
222     mem->response[mem->size] = 0;
223
224     return realsize;
225 }