diff --git a/c/keyval.c b/c/keyval.c index 0a17d06..cf8fa9b 100644 --- a/c/keyval.c +++ b/c/keyval.c @@ -3,7 +3,6 @@ #include "keyval.h" #include "utils.h" -#include #include #include diff --git a/c/response.c b/c/response.c index 66c963a..72f31d8 100644 --- a/c/response.c +++ b/c/response.c @@ -6,22 +6,24 @@ #include #include -static size_t calc_res_headers_sz(const rpd_res *res); +static size_t calc_res_status_sz(const rpd_res *res); + +static size_t calc_res_headers_sz(const rpd_keyval *res); void rpd_res_init(rpd_res *dest) { dest->status = rpd_res_st_ok; - dest->location = dest->content_type = NULL; dest->body = NULL; - - rpd_keyval_init(&dest->cookie, 0); + rpd_keyval_init(&dest->headers, 5); } int rpd_res_headers_str(char **dest, const rpd_res *src) { - size_t size = calc_res_headers_sz(src); + size_t size, i = 0; char *ptr; + size = calc_res_headers_sz(&src->headers); + *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { perror("malloc"); @@ -29,12 +31,13 @@ int rpd_res_headers_str(char **dest, const rpd_res *src) } ptr = *dest; - if (src->content_type) { - ptr += sprintf(ptr, "Content-Type: %s\r\n", src->content_type); - } - - if (src->location) { - ptr += sprintf(ptr, "Location: %s\r\n", src->location); + while (i < src->headers.size) { + ptr += sprintf( + ptr, + "%s: %s\r\n", + src->headers.items[i].key, + src->headers.items[i].val); + i++; } return 0; @@ -44,7 +47,9 @@ int rpd_res_str(char **dest, const rpd_res *res) { size_t headers_size, size; char *ptr, *headers; - size = headers_size = calc_res_headers_sz(res); + size = headers_size = calc_res_headers_sz(&res->headers); + size += calc_res_status_sz(res); + if (res->body) size += 2 + strlen(res->body); @@ -78,25 +83,24 @@ int rpd_res_str(char **dest, const rpd_res *res) return 0; } -static size_t calc_res_headers_sz(const rpd_res *res) +static size_t calc_res_status_sz(const rpd_res *res) { size_t size = 0; + size += strlen("Status: \r\n"); + size += 3; /* plus status code */ + return size; +} - size += strlen("Status: \r\n") + 3; - if (res->location) { - size += strlen("Location: \r\n") + strlen(res->location); - } - - if (res->content_type) { - size += strlen("Content-Type: \r\n") + strlen(res->content_type); - } - - if (res->cookie.size) { - size += strlen("Set-Cookie: \r\n") * res->cookie.size; - for (int i = 0; i < res->cookie.size; i++) { - rpd_keyval_item *item = res->cookie.items + i; - size += strlen(item->key) + strlen(item->val); - } +static size_t calc_res_headers_sz(const rpd_keyval *headers) +{ + size_t size = 0, i = 0; + + while (i < headers->size) { + size += strlen(headers->items[i].key); + size++; /* plus space */ + size += strlen(headers->items[i].val); + size += 2; /* plus CRLF */ + i++; } return size; @@ -106,22 +110,12 @@ void rpd_res_cleanup(rpd_res *res) { res->status = rpd_res_st_ok; - if (res->location) { - free(res->location); - res->location = NULL; - } - - if (res->content_type) { - free(res->content_type); - res->content_type = NULL; - } - if (res->body) { free(res->body); res->body = NULL; } - if (res->cookie.capacity) { - rpd_keyval_cleanup(&res->cookie); + if (res->headers.capacity) { + rpd_keyval_cleanup(&res->headers); } } diff --git a/cxx/Response.cxx b/cxx/Response.cxx index 0917f18..b9f95fa 100644 --- a/cxx/Response.cxx +++ b/cxx/Response.cxx @@ -9,6 +9,14 @@ using namespace rpd; +int Response::header(const char *key, const char *value) +{ + return rpd_keyval_insert( + &this->res->headers, + key, + value); +} + #ifdef EXTENSIONS_INJA void Response::render(const char *path, nlohmann::json data) { diff --git a/examples/c/example.c b/examples/c/example.c index b3a2089..4770985 100644 --- a/examples/c/example.c +++ b/examples/c/example.c @@ -28,6 +28,7 @@ static void products_handler(rpd_req *req, rpd_res *res, void *userdata) int bufflen = strlen(body) + strlen(cat->val) + strlen(id->val); res->body = (char *) malloc(sizeof(char) * (bufflen + 1)); if (!res->body) { + perror("malloc"); res->status = rpd_res_st_internal_server_error; return; } @@ -37,12 +38,7 @@ static void products_handler(rpd_req *req, rpd_res *res, void *userdata) res->status = rpd_res_st_ok; - /* - * place all values in heap, please, - * because after call handler - * `req` and `res` will be freed - */ - res->content_type = strdup("text/html"); + rpd_keyval_insert(&res->headers, "Content-Type", "text/html"); } int main() diff --git a/examples/c/minimal.c b/examples/c/minimal.c index ec4583a..6c58087 100644 --- a/examples/c/minimal.c +++ b/examples/c/minimal.c @@ -15,15 +15,18 @@ static void home_page_handler(rpd_req *req, rpd_res *res, void *userdata) /* Check request method */ switch (req->method) { case HEAD: - /* Process GET request */ res->status = rpd_res_st_ok; + rpd_keyval_insert(&res->headers, "Content-Type", "text/plain"); + break; + case GET: + res->status = rpd_res_st_ok; + rpd_keyval_insert(&res->headers, "Content-Type", "text/plain"); + rpd_keyval_insert(&res->headers, "JavaScript", "Sucks"); - /* Please allocate data on the heap, + /* Please allocate body on the heap, * because after calling this handler - * Rapida will free it all. + * Rapida will free it. */ - res->content_type = strdup("text/plain"); - case GET: res->body = strdup("Hello World!"); break; default: diff --git a/examples/cxx/example.cxx b/examples/cxx/example.cxx index 85480b3..6cc303e 100644 --- a/examples/cxx/example.cxx +++ b/examples/cxx/example.cxx @@ -35,7 +35,7 @@ protected: virtual void handle_head(const rpd::Request &req, rpd::Response &res) override { res.status(rpd_res_st_ok); - res.content_type("text/html"); + res.header("Content-Type", "text/html"); } }; diff --git a/examples/cxx/minimal.cxx b/examples/cxx/minimal.cxx index d8febda..3bb0fa1 100644 --- a/examples/cxx/minimal.cxx +++ b/examples/cxx/minimal.cxx @@ -1,7 +1,6 @@ #include "../../include/rapida.hxx" #include "../../include/servers/tcp.h" - /* * \brief Home page route handler. */ @@ -29,7 +28,7 @@ protected: virtual void handle_head(const rpd::Request &req, rpd::Response &res) override { res.status(rpd_res_st_ok); - res.content_type("text/plain"); + res.header("Content-Type", "text/plain"); } }; diff --git a/include/Response.hxx b/include/Response.hxx index 75db59a..9d7fee1 100644 --- a/include/Response.hxx +++ b/include/Response.hxx @@ -59,43 +59,14 @@ public: } /*! - * \brief Sets _location_ response field. + * \brief Sets response header. * - * \param location Location URL. - */ - void location(const char *location) - { - if (res->location) - free(res->location); - res->location = strdup(location); - } - - /*! - * \brief Sets _Content-Type_ response field. - * - * \param content_type Response content type. - */ - void content_type(const char *content_type) - { - if (res->content_type) - free(res->content_type); - res->content_type = strdup(content_type); - } - - /*! - * \brief Sets cookie field. + * \param key Header key. + * \param value Header value * - * Adds new cookie field to key-value storage. - * If you need to set cookie parameters such as lifetime, - * place it to val. - * - * \param key Cookie field key. - * \param val Cookie field value. + * \return Status code. 0 is success. */ - void cookie(const char *key, const char *val) - { - rpd_keyval_insert(&res->cookie, key, val); - } + int header(const char *key, const char *value); /*! * \brief Sets response body. diff --git a/include/keyval.h b/include/keyval.h index 60c270b..4c91307 100644 --- a/include/keyval.h +++ b/include/keyval.h @@ -9,7 +9,7 @@ #ifndef RAPIDA_KEYVAL_H_ENTRY #define RAPIDA_KEYVAL_H_ENTRY -#include "unistd.h" +#include #ifdef __cplusplus extern "C" { diff --git a/include/response.h b/include/response.h index 6e6d64e..3cd949a 100644 --- a/include/response.h +++ b/include/response.h @@ -86,10 +86,8 @@ enum rpd_res_statuses { */ typedef struct { enum rpd_res_statuses status; /**< Response status code. */ - char *location; /**< Location field. */ - char *content_type; /**< Content type. */ char *body; /**< Response body. */ - rpd_keyval cookie; /**< Set-Cookie fields. */ + rpd_keyval headers; /**< Response headers. */ } rpd_res; /*! diff --git a/servers/tcp.c b/servers/tcp.c index 89e4df6..3b993fb 100644 --- a/servers/tcp.c +++ b/servers/tcp.c @@ -64,6 +64,7 @@ static void handle_request(struct mg_connection *conn, int ev, void *ev_data, vo rpd_app_handle_request((rpd_app *) app, req, res); rpd_res_headers_str(&headers_buff, res); + puts(headers_buff); mg_http_reply(conn, res->status, headers_buff, res->body ? res->body : ""); free(headers_buff);