Browse Source

setting response headers using function instead of struct fields

pull/2/head
Ivan Polyakov 2 years ago
parent
commit
ec7fd1d728
  1. 1
      c/keyval.c
  2. 70
      c/response.c
  3. 8
      cxx/Response.cxx
  4. 8
      examples/c/example.c
  5. 13
      examples/c/minimal.c
  6. 2
      examples/cxx/example.cxx
  7. 3
      examples/cxx/minimal.cxx
  8. 39
      include/Response.hxx
  9. 2
      include/keyval.h
  10. 4
      include/response.h
  11. 1
      servers/tcp.c

1
c/keyval.c

@ -3,7 +3,6 @@
#include "keyval.h" #include "keyval.h"
#include "utils.h" #include "utils.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

70
c/response.c

@ -6,22 +6,24 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
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) void rpd_res_init(rpd_res *dest)
{ {
dest->status = rpd_res_st_ok; dest->status = rpd_res_st_ok;
dest->location = dest->content_type = NULL;
dest->body = NULL; dest->body = NULL;
rpd_keyval_init(&dest->headers, 5);
rpd_keyval_init(&dest->cookie, 0);
} }
int rpd_res_headers_str(char **dest, const rpd_res *src) 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; char *ptr;
size = calc_res_headers_sz(&src->headers);
*dest = (char *) malloc(sizeof(char) * size); *dest = (char *) malloc(sizeof(char) * size);
if (!*dest) { if (!*dest) {
perror("malloc"); perror("malloc");
@ -29,12 +31,13 @@ int rpd_res_headers_str(char **dest, const rpd_res *src)
} }
ptr = *dest; ptr = *dest;
if (src->content_type) { while (i < src->headers.size) {
ptr += sprintf(ptr, "Content-Type: %s\r\n", src->content_type); ptr += sprintf(
} ptr,
"%s: %s\r\n",
if (src->location) { src->headers.items[i].key,
ptr += sprintf(ptr, "Location: %s\r\n", src->location); src->headers.items[i].val);
i++;
} }
return 0; return 0;
@ -44,7 +47,9 @@ int rpd_res_str(char **dest, const rpd_res *res)
{ {
size_t headers_size, size; size_t headers_size, size;
char *ptr, *headers; 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) if (res->body)
size += 2 + strlen(res->body); size += 2 + strlen(res->body);
@ -78,25 +83,24 @@ int rpd_res_str(char **dest, const rpd_res *res)
return 0; 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_t size = 0;
size += strlen("Status: \r\n");
size += strlen("Status: \r\n") + 3; size += 3; /* plus status code */
if (res->location) { return size;
size += strlen("Location: \r\n") + strlen(res->location);
} }
if (res->content_type) { static size_t calc_res_headers_sz(const rpd_keyval *headers)
size += strlen("Content-Type: \r\n") + strlen(res->content_type); {
} size_t size = 0, i = 0;
if (res->cookie.size) { while (i < headers->size) {
size += strlen("Set-Cookie: \r\n") * res->cookie.size; size += strlen(headers->items[i].key);
for (int i = 0; i < res->cookie.size; i++) { size++; /* plus space */
rpd_keyval_item *item = res->cookie.items + i; size += strlen(headers->items[i].val);
size += strlen(item->key) + strlen(item->val); size += 2; /* plus CRLF */
} i++;
} }
return size; return size;
@ -106,22 +110,12 @@ void rpd_res_cleanup(rpd_res *res)
{ {
res->status = rpd_res_st_ok; 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) { if (res->body) {
free(res->body); free(res->body);
res->body = NULL; res->body = NULL;
} }
if (res->cookie.capacity) { if (res->headers.capacity) {
rpd_keyval_cleanup(&res->cookie); rpd_keyval_cleanup(&res->headers);
} }
} }

8
cxx/Response.cxx

@ -9,6 +9,14 @@
using namespace rpd; using namespace rpd;
int Response::header(const char *key, const char *value)
{
return rpd_keyval_insert(
&this->res->headers,
key,
value);
}
#ifdef EXTENSIONS_INJA #ifdef EXTENSIONS_INJA
void Response::render(const char *path, nlohmann::json data) void Response::render(const char *path, nlohmann::json data)
{ {

8
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); int bufflen = strlen(body) + strlen(cat->val) + strlen(id->val);
res->body = (char *) malloc(sizeof(char) * (bufflen + 1)); res->body = (char *) malloc(sizeof(char) * (bufflen + 1));
if (!res->body) { if (!res->body) {
perror("malloc");
res->status = rpd_res_st_internal_server_error; res->status = rpd_res_st_internal_server_error;
return; return;
} }
@ -37,12 +38,7 @@ static void products_handler(rpd_req *req, rpd_res *res, void *userdata)
res->status = rpd_res_st_ok; res->status = rpd_res_st_ok;
/* rpd_keyval_insert(&res->headers, "Content-Type", "text/html");
* place all values in heap, please,
* because after call handler
* `req` and `res` will be freed
*/
res->content_type = strdup("text/html");
} }
int main() int main()

13
examples/c/minimal.c

@ -15,15 +15,18 @@ static void home_page_handler(rpd_req *req, rpd_res *res, void *userdata)
/* Check request method */ /* Check request method */
switch (req->method) { switch (req->method) {
case HEAD: case HEAD:
/* Process GET request */
res->status = rpd_res_st_ok; 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 * 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!"); res->body = strdup("Hello World!");
break; break;
default: default:

2
examples/cxx/example.cxx

@ -35,7 +35,7 @@ protected:
virtual void handle_head(const rpd::Request &req, rpd::Response &res) override virtual void handle_head(const rpd::Request &req, rpd::Response &res) override
{ {
res.status(rpd_res_st_ok); res.status(rpd_res_st_ok);
res.content_type("text/html"); res.header("Content-Type", "text/html");
} }
}; };

3
examples/cxx/minimal.cxx

@ -1,7 +1,6 @@
#include "../../include/rapida.hxx" #include "../../include/rapida.hxx"
#include "../../include/servers/tcp.h" #include "../../include/servers/tcp.h"
/* /*
* \brief Home page route handler. * \brief Home page route handler.
*/ */
@ -29,7 +28,7 @@ protected:
virtual void handle_head(const rpd::Request &req, rpd::Response &res) override virtual void handle_head(const rpd::Request &req, rpd::Response &res) override
{ {
res.status(rpd_res_st_ok); res.status(rpd_res_st_ok);
res.content_type("text/plain"); res.header("Content-Type", "text/plain");
} }
}; };

39
include/Response.hxx

@ -59,43 +59,14 @@ public:
} }
/*! /*!
* \brief Sets _location_ response field. * \brief Sets response header.
* *
* \param location Location URL. * \param key Header key.
*/ * \param value Header value
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.
* *
* Adds new cookie field to key-value storage. * \return Status code. 0 is success.
* If you need to set cookie parameters such as lifetime,
* place it to val.
*
* \param key Cookie field key.
* \param val Cookie field value.
*/ */
void cookie(const char *key, const char *val) int header(const char *key, const char *value);
{
rpd_keyval_insert(&res->cookie, key, val);
}
/*! /*!
* \brief Sets response body. * \brief Sets response body.

2
include/keyval.h

@ -9,7 +9,7 @@
#ifndef RAPIDA_KEYVAL_H_ENTRY #ifndef RAPIDA_KEYVAL_H_ENTRY
#define RAPIDA_KEYVAL_H_ENTRY #define RAPIDA_KEYVAL_H_ENTRY
#include "unistd.h" #include <unistd.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

4
include/response.h

@ -86,10 +86,8 @@ enum rpd_res_statuses {
*/ */
typedef struct { typedef struct {
enum rpd_res_statuses status; /**< Response status code. */ enum rpd_res_statuses status; /**< Response status code. */
char *location; /**< Location field. */
char *content_type; /**< Content type. */
char *body; /**< Response body. */ char *body; /**< Response body. */
rpd_keyval cookie; /**< Set-Cookie fields. */ rpd_keyval headers; /**< Response headers. */
} rpd_res; } rpd_res;
/*! /*!

1
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_app_handle_request((rpd_app *) app, req, res);
rpd_res_headers_str(&headers_buff, res); rpd_res_headers_str(&headers_buff, res);
puts(headers_buff);
mg_http_reply(conn, res->status, headers_buff, res->body ? res->body : ""); mg_http_reply(conn, res->status, headers_buff, res->body ? res->body : "");
free(headers_buff); free(headers_buff);

Loading…
Cancel
Save