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