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