rsstats 0.0.1
Redis Enterprise Statistic collector
libhttp.c
Go to the documentation of this file.
1
19#include "libhttp.h"
20#include "sclist.h"
21#include "base64.h" /* Base64 encoder and decoder */
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <assert.h>
27
28typedef struct HTTP_s {
30 char* body;
32
33typedef struct HTTPHeader_s {
35 char* name;
36 char* value;
38
40 char* newname;
41
42 assert(header);
43 assert(header->name);
44 assert(header->value);
45
46 if (NULL==(newname=realloc(header->name,strlen(name)+1))) {
47 perror("HTTPHeader_setname realloc");
48 return NULL;
49 }
50 header->name = newname;
51 strcpy(header->name,name);
52 return header;
53}
54
56 assert(header);
57 assert(header->name);
58 assert(header->value);
59
60 return header->name;
61}
62
63HTTPHeader_t* HTTPHeader_setvalue(HTTPHeader_t* header, const char* value) {
64 char* newvalue;
65
66 assert(header);
67 assert(header->name);
68 assert(header->value);
69
70 if (NULL==(newvalue=realloc(header->value,strlen(value)+1))) {
71 perror("HTTPHeader_setvalue realloc");
72 return NULL;
73 }
74 header->value = newvalue;
75 strcpy(header->value,value);
76 return header;
77}
78
80 assert(header);
81 assert(header->name);
82 assert(header->value);
83
84 return header->value;
85}
86
87static HTTPHeader_t* HTTPHeader_new(const char* name, const char* value) {
88 HTTPHeader_t* header;
89
90 assert(name);
91 assert(value);
92
93 if (NULL==(header=malloc(sizeof(struct HTTPHeader_s)))) {
94 perror("HTTPHeader_new");
95 return NULL;
96 }
97 if (NULL==(header->name=strdup(name))) {
98 perror("HTTPHeader_new name");
99 free(header);
100 return NULL;
101 }
102 if (NULL==(header->value=strdup(value))) {
103 perror("HTTPHeader_new value");
104 free(header->name);
105 free(header);
106 return NULL;
107 }
108 header->self = NULL;
109 return header;
110}
111
112static void HTTPHeader_del(HTTPHeader_t* header) {
113 assert(header);
114 assert(header->name);
115 assert(header->value);
116
117 free(header->name);
118 free(header->value);
119 free(header);
120}
121
123 HTTP_t* http;
124
125 if (NULL==(http=malloc(sizeof(struct HTTP_s)))) {
126 perror("HTTP_new HTTP_s");
127 return NULL;
128 }
129
130 if (NULL==(http->body=strdup(""))) {
131 perror("HTTP_new body");
132 free(http);
133 return NULL;
134 };
135
136 if (NULL==(http->headers = sclist_new())) {
137 perror("HTTP_new headers");
138 free(http->body);
139 free(http);
140 return NULL;
141 }
142
143 return http;
144}
145
146void HTTP_del(HTTP_t* http) {
147 sclistrecord_t* headerlst_entry;
148
149 assert(http);
150 assert(http->headers);
151 assert(http->body);
152
153 headerlst_entry = sclist_firstrecord(http->headers);
154 while (headerlst_entry) {
155 HTTPHeader_t* headerlst_value;
156
157 /* Free payload */
158 headerlst_value=sclist_getvalue(headerlst_entry);
159 HTTPHeader_del(headerlst_value);
160
161 /* Remember the entry to delete before moving to the next one */
162 sclistrecord_t* tmp = headerlst_entry;
163 headerlst_entry = sclist_nextrecord(headerlst_entry);
164 sclist_remrecord(http->headers,tmp);
165 }
166
167 free(http->body);
168 free(http);
169}
170
171HTTP_t* HTTP_setbody(HTTP_t* http, const char* body) {
172 char* newbody;
173
174 assert(http);
175 assert(http->headers);
176 assert(http->body);
177 assert(body);
178
179 if (NULL==(newbody=realloc(http->body,strlen(body)+1))) {
180 perror("HTTP_setbody realloc");
181 return NULL;
182 }
183
184 http->body = newbody;
185 strcpy(http->body, body);
186 return http;
187}
188
189char* HTTP_getbody(HTTP_t* http) {
190 assert(http);
191 assert(http->headers);
192 assert(http->body);
193
194 return http->body;
195}
196
197HTTPHeader_t* HTTP_addheader(HTTP_t* http, const char* name, const char* value) {
198 HTTPHeader_t* header;
199
200 assert(http);
201 assert(http->headers);
202 assert(http->body);
203 assert(name);
204 assert(value);
205
206 if (NULL==(header = HTTPHeader_new(name,value))) {
207 perror("HTTP_addheader HTTPHeader_new");
208 return NULL;
209 }
210
211 if (NULL==(header->self=sclist_addrecord(http->headers,header))) {
212 perror("HTTP_addheader");
213 HTTPHeader_del(header);
214 return NULL;
215 }
216 return header;
217}
218
219HTTPHeader_t* HTTP_addbasicauth(HTTP_t* http, const char* login, const char* pass) {
220 char* auth_encoded;
221 char* auth;
222 HTTPHeader_t* header;
223
224 assert(http);
225 assert(http->headers);
226 assert(http->body);
227 assert(login);
228 assert(pass);
229
230 if (NULL==(auth=malloc(strlen(login)+1+strlen(pass)+1))) {
231 perror("HTTP_addbasicauth credentials");
232 return NULL;
233 }
234 /* strcpy/strcat expected to be faster than sprintf */
235 strcpy(auth,login);
236 strcat(auth,":");
237 strcat(auth,pass);
238 auth_encoded=base64_encode(auth);
239 free(auth);
240
241 if (NULL==(auth=malloc(strlen("Basic ")+strlen(auth_encoded)+1))) {
242 perror("HTTP_addbasicauth value");
243 free(auth_encoded);
244 return NULL;
245 }
246 strcpy(auth,"Basic ");
247 strcat(auth, auth_encoded);
248 free(auth_encoded);
249
250 if (NULL==(header=HTTP_addheader(http,"Authorization",auth))) {
251 perror("HTTP_addbasicauth addheader");
252 free(auth);
253 return NULL;
254 }
255 free(auth);
256 return header;
257}
258
260 sclistrecord_t* headerlst_entry;
261
262 assert(http);
263 assert(http->headers);
264 assert(http->body);
265
266 if (NULL==(headerlst_entry=sclist_firstrecord(http->headers)))
267 return NULL;
268 return sclist_getvalue(headerlst_entry);
269}
270
272 sclistrecord_t* headerlst_entry;
273
274 assert(header);
275 assert(header->self);
276 assert(header->name);
277 assert(header->value);
278
279 headerlst_entry = header->self;
280
281 /* EOL reached */
282 if (NULL==(headerlst_entry = sclist_nextrecord(headerlst_entry)))
283 return NULL;
284 else
285 return sclist_getvalue(headerlst_entry);
286}
287
288HTTPHeader_t* HTTP_findheader(const HTTPHeader_t* start, const char* name) {
289 sclistrecord_t* headerlst_entry;
290
291 assert(start);
292 assert(start->self);
293 assert(start->name);
294 assert(start->value);
295 assert(name);
296
297 headerlst_entry = start->self;
298
299 while (headerlst_entry) {
300 HTTPHeader_t* headerlst_value;
301 char* header_name;
302
303 headerlst_value = sclist_getvalue(headerlst_entry);
304 assert(headerlst_value);
305 header_name = HTTPHeader_getname(headerlst_value);
306 if (0==strcmp(header_name,name))
307 break;
308 headerlst_entry=sclist_nextrecord(headerlst_entry);
309 }
310 if (!headerlst_entry)
311 /* Not found */
312 return NULL;
313 else
314 /* Found */
315 return sclist_getvalue(headerlst_entry);
316}
317
318
320 assert(http);
321 assert(http->headers);
322 assert(http->body);
323 assert(header);
324 assert(header->self);
325 assert(header->name);
326 assert(header->value);
327
328 /* Remove from the header list */
329 sclist_remrecord(http->headers, header->self);
331#if 0
332 if (NULL==sclist_remrecord(http->headers, header->sclistrecord)) {
333 perror("HTTP_addheader");
334 return NULL;
335 }
336#endif
337 header->self = NULL;
338 HTTPHeader_del(header);
339
340 return http;
341}
342
343static char* strconcat(char* dst, char* src) {
344 char* newdst;
345
346 assert(dst);
347 assert(src);
348
349 if (NULL==(newdst=realloc(dst,strlen(dst)+strlen(src)+1))) {
350 perror("strconcat");
351 return NULL;
352 }
353 dst = newdst;
354 strcat(dst,src);
355 return dst;
356}
357
358char* HTTP_buildheaders(const HTTP_t* http) {
359 char* headers_str=NULL;
360 sclistrecord_t* headerlst_entry;
361
362 assert(http);
363 assert(http->headers);
364 assert(http->body);
365
366 if (NULL==(headers_str=strdup(""))) {
367 perror("HTTP_buildheaders headers_str");
368 return NULL;
369 }
370 for (headerlst_entry=sclist_firstrecord(http->headers); headerlst_entry; headerlst_entry = sclist_nextrecord(headerlst_entry)) {
371 HTTPHeader_t* headerlst_value;
372
373 headerlst_value = sclist_getvalue(headerlst_entry);
374 assert(headerlst_value);
376 headers_str=strconcat(headers_str,HTTPHeader_getname(headerlst_value));
377 headers_str=strconcat(headers_str,": ");
378 headers_str=strconcat(headers_str,HTTPHeader_getvalue(headerlst_value));
379 headers_str=strconcat(headers_str,"\r\n");
380 }
381
382 return headers_str;
383}
384
385
386
387
388
389
390
391
392
393
394
395
396
397char* HTTP_buildrequest(const HTTPMethod_t method, const char* uri, const HTTPVersion_t version) {
398 char* retval;
399
400 assert(method<=HTTPMETHOD_INVALID);
401 assert(uri);
402 assert(version<=HTTPVERSION_INVALID);
403
404 if (NULL==(retval=malloc(7+1+strlen(uri)+1+8+1))) {
405 perror("HTTP_getrequest");
406 exit(EXIT_FAILURE);
407 }
408 retval[0]=0;
409
410 switch(method) {
411 case HTTPMETHOD_GET:
412 strcat(retval, "GET");
413 break;;
414 case HTTPMETHOD_HEAD:
415 case HTTPMETHOD_POST:
416 case HTTPMETHOD_PUT:
420 case HTTPMETHOD_TRACE:
421 case HTTPMETHOD_PATCH:
423 default:
424 fprintf(stderr,"HTTP method not supported\n");
425 exit(EXIT_FAILURE);
426 break;;
427 }
428
429 if (uri[0]) {
430 strcat(retval," ");
431 strcat(retval, uri);
432 }
433
434 strcat(retval," HTTP/");
435 switch(version) {
438 strcat(retval, "1.1");
439 break;;
445 default:
446 fprintf(stderr,"HTTP version not supported\n");
447 exit(EXIT_FAILURE);
448 break;;
449 }
450 strcat(retval, "\r\n");
451 return retval;
452}
453
char * base64_encode(char *plain)
Encode a zero terminated C string in Base64.
Definition: base64.c:39
Simple Base64 encoding and decoding functions.
const char *const name
Definition: cJSON.h:268
HTTPHeader_t * HTTP_firstheader(const HTTP_t *http)
Definition: libhttp.c:259
char * HTTPHeader_getvalue(HTTPHeader_t *header)
Definition: libhttp.c:79
HTTP_t * HTTP_remheader(HTTP_t *http, HTTPHeader_t *header)
Definition: libhttp.c:319
void HTTP_del(HTTP_t *http)
Definition: libhttp.c:146
char * HTTP_buildheaders(const HTTP_t *http)
Definition: libhttp.c:358
struct HTTP_s HTTP_t
HTTP_t * HTTP_new()
Definition: libhttp.c:122
struct HTTPHeader_s HTTPHeader_t
HTTPHeader_t * HTTP_addbasicauth(HTTP_t *http, const char *login, const char *pass)
Definition: libhttp.c:219
char * HTTP_getbody(HTTP_t *http)
Definition: libhttp.c:189
char * HTTPHeader_getname(HTTPHeader_t *header)
Definition: libhttp.c:55
HTTPHeader_t * HTTPHeader_setname(HTTPHeader_t *header, const char *name)
Definition: libhttp.c:39
HTTPHeader_t * HTTP_findheader(const HTTPHeader_t *start, const char *name)
Definition: libhttp.c:288
HTTP_t * HTTP_setbody(HTTP_t *http, const char *body)
Definition: libhttp.c:171
HTTPHeader_t * HTTP_addheader(HTTP_t *http, const char *name, const char *value)
Definition: libhttp.c:197
char * HTTP_buildrequest(const HTTPMethod_t method, const char *uri, const HTTPVersion_t version)
Definition: libhttp.c:397
HTTPHeader_t * HTTPHeader_setvalue(HTTPHeader_t *header, const char *value)
Definition: libhttp.c:63
HTTPHeader_t * HTTP_nextheader(const HTTPHeader_t *header)
Definition: libhttp.c:271
HTTP parsing and building library.
enum HTTPVersion_e HTTPVersion_t
@ HTTPMETHOD_PUT
Definition: libhttp.h:38
@ HTTPMETHOD_POST
Definition: libhttp.h:37
@ HTTPMETHOD_CONNECT
Definition: libhttp.h:40
@ HTTPMETHOD_TRACE
Definition: libhttp.h:42
@ HTTPMETHOD_PATCH
Definition: libhttp.h:43
@ HTTPMETHOD_DELETE
Definition: libhttp.h:39
@ HTTPMETHOD_OPTIONS
Definition: libhttp.h:41
@ HTTPMETHOD_GET
Definition: libhttp.h:35
@ HTTPMETHOD_INVALID
Definition: libhttp.h:44
@ HTTPMETHOD_HEAD
Definition: libhttp.h:36
@ HTTPVERSION_HTTP11b
Definition: libhttp.h:28
@ HTTPVERSION_INVALID
Definition: libhttp.h:31
@ HTTPVERSION_HTTP09
Definition: libhttp.h:25
@ HTTPVERSION_HTTP2
Definition: libhttp.h:29
@ HTTPVERSION_HTTP10
Definition: libhttp.h:26
@ HTTPVERSION_HTTP3
Definition: libhttp.h:30
@ HTTPVERSION_HTTP11
Definition: libhttp.h:27
enum HTTPMethod_e HTTPMethod_t
#define NULL
Definition: rsstats-opts.c:64
void * sclist_getvalue(sclistrecord_t *record)
Returns the value pointer stored in the record.
Definition: sclist.c:127
sclist_t * sclist_new()
Allocate and initialize the internal list structure.
Definition: sclist.c:39
sclistrecord_t * sclist_nextrecord(const sclistrecord_t *record)
Returns the pointer on the record following the specified one.
Definition: sclist.c:121
sclistrecord_t * sclist_addrecord(sclist_t *sclist, void *value)
Add a value at the end of the list.
Definition: sclist.c:62
sclistrecord_t * sclist_firstrecord(const sclist_t *sclist)
Returns the pointer on the first list record.
Definition: sclist.c:115
void sclist_remrecord(sclist_t *sclist, sclistrecord_t *record)
Remove a record in a list.
Definition: sclist.c:90
Basic single chained generic list.
Definition: libhttp.c:28
char * body
Definition: libhttp.c:30
sclist_t * headers
Definition: libhttp.c:29
char * value
Definition: libhttp.c:36
sclistrecord_t * self
Definition: libhttp.c:34
char * name
Definition: libhttp.c:35
Opaque sclist structure.
Definition: sclist.c:34
Private list record structure.
Definition: sclist.c:27