diff --git a/examples/client/000_get_request.c b/examples/client/000_get_request.c new file mode 100644 index 0000000..88148e3 --- /dev/null +++ b/examples/client/000_get_request.c @@ -0,0 +1,58 @@ +#include + +// This is an example of how to use cHTTP to perform +// a basic GET request. + +int main(void) +{ + http_global_init(); + + // List any headers the request should hold + HTTP_String headers[] = { + HTTP_STR("User-Agent: cHTTP"), + }; + + // Request handle that will be necessary to + // free the request's resources when we are + // done with the result. + HTTP_RequestHandle handle; + + // Perform the request. This will block the thread + // until an error occurs or the request completes. + HTTP_Response *res = http_get( + HTTP_STR("http://example.com/index.html"), + headers, HTTP_COUNT(headers), + &handle + ); + + // The http_get function returns NULL if the request + // couldn't be performed. + if (res == NULL) return -1; + + // If the request succeded (note that responses with + // status 4xx and 5xx are not considered as errors in + // this context) the returned value holds the parsed + // version of the response and the output handle is set. + + printf("status code: %d\n", res->status); + + for (int i = 0; i < res->num_headers; i++) { + HTTP_Header header = res->headers[i]; + printf( + "header %d: [%.*s] [%.*s]\n", + i, + HTTP_UNPACK(header.name), + HTTP_UNPACK(header.value) + ); + } + + printf("body: %.*s\n", res->body.len, res->body.ptr); + + // When we are done reading from the response object + // we must free the request's resources. + http_request_free(handle); + + // All done. Deinitialize the library. + http_global_free(); + return 0; +} \ No newline at end of file diff --git a/src/basic.h b/src/basic.h index ce4cb19..e5c1f05 100644 --- a/src/basic.h +++ b/src/basic.h @@ -47,6 +47,9 @@ HTTP_String http_trim(HTTP_String s); // Returns the number of items of a static array. #define HTTP_COUNT(X) (sizeof(X) / sizeof((X)[0])) +// TODO: comment +#define HTTP_UNPACK(X) (X).len, (X).ptr + // Macro used to make invariants of the code more explicit. // // Say you have some function that operates on two integers diff --git a/src/client.c b/src/client.c index 3e90bd5..de1b99f 100644 --- a/src/client.c +++ b/src/client.c @@ -370,4 +370,83 @@ void http_request_free(HTTP_RequestHandle handle) socket_free(&conn->socket); conn->state = CLIENT_CONNECTION_FREE; client->num_conns--; +} + +static HTTP_Client *default_client___; // TODO: deinitialize the default client when http_global_free is called + +static HTTP_Client *get_default_client(void) +{ + if (default_client___ == NULL) + default_client___ = http_client_init(); + return default_client___; +} + +HTTP_Response *http_get(HTTP_String url, HTTP_String *headers, int num_headers, HTTP_RequestHandle *phandle) +{ + HTTP_Client *client = get_default_client(); + if (client == NULL) + return NULL; + + HTTP_RequestHandle handle; + int ret = http_client_request(client, &handle); + if (ret < 0) + return NULL; + + http_request_line(handle, HTTP_METHOD_GET, url); + + for (int i = 0; i < num_headers; i++) + http_request_header(handle, headers[i]); + + http_request_submit(handle); + + ret = http_client_wait(client, NULL); // TODO: it's assumed there is only one request pending + if (ret < 0) { + http_request_free(handle); // TODO: currently free only works on completed request handles + return NULL; + } + + HTTP_Response *res = http_request_result(handle); + if (res == NULL) { + http_request_free(handle); + return NULL; + } + + *phandle = handle; + return res; +} + +HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers, HTTP_String body, HTTP_RequestHandle *phandle) +{ + HTTP_Client *client = get_default_client(); + if (client == NULL) + return NULL; + + HTTP_RequestHandle handle; + int ret = http_client_request(client, &handle); + if (ret < 0) + return NULL; + + http_request_line(handle, HTTP_METHOD_GET, url); + + for (int i = 0; i < num_headers; i++) + http_request_header(handle, headers[i]); + + http_request_body(handle, body); + + http_request_submit(handle); + + ret = http_client_wait(client, NULL); // TODO: it's assumed there is only one request pending + if (ret < 0) { + http_request_free(handle); // TODO: currently free only works on completed request handles + return NULL; + } + + HTTP_Response *res = http_request_result(handle); + if (res == NULL) { + http_request_free(handle); + return NULL; + } + + *phandle = handle; + return res; } \ No newline at end of file diff --git a/src/client.h b/src/client.h index ad534c6..693dc2b 100644 --- a/src/client.h +++ b/src/client.h @@ -94,4 +94,14 @@ HTTP_Response *http_request_result(HTTP_RequestHandle handle); // TODO: allow aborting pending requests void http_request_free(HTTP_RequestHandle handle); +// TODO: comment +HTTP_Response *http_get(HTTP_String url, + HTTP_String *headers, int num_headers, + HTTP_RequestHandle *phandle); + +// TODO: comment +HTTP_Response *http_post(HTTP_String url, + HTTP_String *headers, int num_headers, + HTTP_String body, HTTP_RequestHandle *phandle); + #endif // CLIENT_INCLUDED \ No newline at end of file