Browse Source

getting all request headers

pull/2/head
Ivan Polyakov 2 years ago
parent
commit
50df05b1b0
  1. 61
      c/utils.c
  2. 17
      c/utils.h
  3. 12
      cxx/Request.cxx
  4. 1
      examples/c/minimal.c
  5. 21
      include/Request.hxx
  6. 3
      include/request.h
  7. 56
      servers/fcgi.c
  8. 17
      servers/tcp.c

61
c/utils.c

@ -2,6 +2,7 @@
/* Copyright 2022 Ivan Polyakov */ /* Copyright 2022 Ivan Polyakov */
#include "utils.h" #include "utils.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -43,3 +44,63 @@ char *rpd_strsep(char **str, const char *sep)
*str = end; *str = end;
return s; return s;
} }
const char *rpd_splitbyc(char **dest1, char **dest2, const char *src, const char sep)
{
const char *start = src, *end = src;
if (!src)
return 0;
while (*end) {
if (*end == sep) {
size_t len = end - start;
*dest1 = malloc(sizeof(char) * (len + 1));
if (!*dest1) {
perror("malloc");
return NULL;
}
memcpy(*dest1, start, len);
(*dest1)[len] = '\0';
end++;
len = strlen(start) - (end - start);
if (!len) {
*dest2 = NULL;
return 0;
}
*dest2 = malloc(sizeof(char) * (len + 1));
if ((!*dest2)) {
perror("malloc");
return NULL;
}
memcpy(*dest2, end, len);
(*dest2)[len + 1] = '\0';
return 0;
}
end++;
}
return 0;
}
void rpd_strerase(char *src, int nchars)
{
char *ptr = NULL;
size_t len = strlen(src);
if (!src)
return;
ptr = src + nchars;
while (*ptr != '\0') {
*(ptr - nchars) = *ptr;
ptr++;
}
ptr = src + len;
while (ptr >= (src + len) - nchars) {
*ptr = '\0';
ptr--;
}
}

17
c/utils.h

@ -10,4 +10,21 @@ char *rpd_strdup(const char *src);
char *rpd_strsep(char **str, const char *sep); char *rpd_strsep(char **str, const char *sep);
const char *rpd_splitbyc(char **dest1, char **dest2, const char *src, const char sep);
/*!
* \brief Erases part of the string.
*
* This function moves characters to the beginning of the string
* and inserts '\0' at the original position without reallocation.
*
* To erase characters not from beginning of the string,
* you can pass a pointer to the beginning of the desired
* part of the string.
*
* \param src String to erase.
* \param nchars Number of charecters to erase.
*/
void rpd_strerase(char *src, int nchars);
#endif /* RAPIDA_UTILS_H_ENTRY */ #endif /* RAPIDA_UTILS_H_ENTRY */

12
cxx/Request.cxx

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2022 Ivan Polyakov */
#include "Request.hxx"
using namespace rpd;
const char *Request::header(const char *key) const
{
rpd_keyval_item *hi = rpd_keyval_find(&req->headers, key);
return hi ? hi->val : NULL;
}

1
examples/c/minimal.c

@ -21,7 +21,6 @@ static void home_page_handler(rpd_req *req, rpd_res *res, void *userdata)
case GET: case GET:
res->status = rpd_res_st_ok; res->status = rpd_res_st_ok;
rpd_keyval_insert(&res->headers, "Content-Type", "text/plain"); rpd_keyval_insert(&res->headers, "Content-Type", "text/plain");
rpd_keyval_insert(&res->headers, "JavaScript", "Sucks");
/* Please allocate body on the heap, /* Please allocate body on the heap,
* because after calling this handler * because after calling this handler

21
include/Request.hxx

@ -69,24 +69,23 @@ public:
} }
/*! /*!
* \brief Gets authorization string. * \brief Gets the request header.
* *
* \return Authorization string. * \params key Header key.
*
* \return Found header or NULL.
*/ */
const char *authorization() const const char *header(const char *key) const;
{
return req->auth;
}
/*! /*!
* \brief Gets cookie string. * \brief Gets all request headers.
* *
* \return Cookie string. * \return Key-value pairs.
*/ */
const char *cookie() const KeyVal headers() const
{ {
return req->cookie; return &req->headers;
}; }
/*! /*!
* \brief Gets request body content. * \brief Gets request body content.

3
include/request.h

@ -36,10 +36,9 @@ enum rpd_req_methods {
*/ */
typedef struct { typedef struct {
enum rpd_req_methods method; /**< Request method. */ enum rpd_req_methods method; /**< Request method. */
char *auth; /**< Authorization field. */
char *cookie; /**< Cookie field. */
char *body; /**< Body field. */ char *body; /**< Body field. */
rpd_url path; /**< Requested URL. */ rpd_url path; /**< Requested URL. */
rpd_keyval headers; /**< Request headers. */
rpd_keyval query; /**< Query. */ rpd_keyval query; /**< Query. */
rpd_keyval params; /**< Dynamic parameters. */ rpd_keyval params; /**< Dynamic parameters. */
} rpd_req; } rpd_req;

56
servers/fcgi.c

@ -2,7 +2,11 @@
/* Copyright 2022 Ivan Polyakov */ /* Copyright 2022 Ivan Polyakov */
#include "../include/servers/fcgi.h" #include "../include/servers/fcgi.h"
#include "../c/utils.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#ifdef MT_ENABLED #ifdef MT_ENABLED
#include <pthread.h> #include <pthread.h>
@ -56,6 +60,8 @@ static int read_fcgx_req_body(char **dest, FCGX_Request *req);
*/ */
static void send_response(rpd_res *res, FCGX_Stream *out); static void send_response(rpd_res *res, FCGX_Stream *out);
static int env_to_req_header(char **key, char **val, const char *envp);
int rpd_fcgi_server_start(rpd_app *app, const char *sock_path) int rpd_fcgi_server_start(rpd_app *app, const char *sock_path)
{ {
FCGX_Init(); FCGX_Init();
@ -155,9 +161,39 @@ static int fcgx_to_rpd_req(rpd_req *dest, FCGX_Request *req)
dest->method = rpd_req_smethod(FCGX_GetParam("REQUEST_METHOD", req->envp)); dest->method = rpd_req_smethod(FCGX_GetParam("REQUEST_METHOD", req->envp));
rpd_url_parse(&dest->path, FCGX_GetParam("DOCUMENT_URI", req->envp)); rpd_url_parse(&dest->path, FCGX_GetParam("DOCUMENT_URI", req->envp));
dest->auth = FCGX_GetParam("HTTP_AUTHORIZATION", req->envp); // dest->auth = FCGX_GetParam("HTTP_AUTHORIZATION", req->envp);
dest->cookie = FCGX_GetParam("HTTP_COOKIE", req->envp); // dest->cookie = FCGX_GetParam("HTTP_COOKIE", req->envp);
rpd_keyval_init(&dest->params, 0); rpd_keyval_init(&dest->params, 0);
rpd_keyval_init(&dest->headers, 0);
char **env = req->envp;
char *key = NULL, *val = NULL;
while (*(++env)) {
char *ptr = NULL;
/* keep only http request fields */
ptr = strstr(*env, "HTTP");
if (ptr == NULL || ptr - *env != 0)
continue;
env_to_req_header(&key, &val, *env);
if (!val || !key)
continue;
rpd_strerase(key, 5);
ptr = key;
while (*ptr) {
*ptr = tolower(*ptr);
if (ptr == key || *(ptr - 1) == '-')
*ptr = toupper(*ptr);
if (*ptr == '_')
*ptr = '-';
ptr++;
}
rpd_keyval_insert(&dest->headers, key, val);
free(key);
free(val);
}
if (dest->method != GET) { if (dest->method != GET) {
if (read_fcgx_req_body(&dest->body, req)) { if (read_fcgx_req_body(&dest->body, req)) {
@ -186,3 +222,19 @@ static int read_fcgx_req_body(char **dest, FCGX_Request *req)
return 0; return 0;
} }
static int env_to_req_header(char **key, char **val, const char *env)
{
const char *ptr = NULL;
rpd_splitbyc(key, val, env, '=');
if (!*key || !*val) {
if (*key)
free(*key);
if (*val)
free(*val);
return 1;
}
return 0;
}

17
servers/tcp.c

@ -45,6 +45,22 @@ static int mg_to_rpd_req(rpd_req *req, struct mg_http_message *msg)
rpd_query_parse(&req->query, tmp); rpd_query_parse(&req->query, tmp);
} }
size_t i, max = sizeof(msg->headers) / sizeof(msg->headers[0]);
rpd_keyval_init(&req->headers, max);
// Iterate over request headers
char *key = NULL, *val = NULL;
for (i = 0; i < max && msg->headers[i].name.len > 0; i++) {
struct mg_str *k = &msg->headers[i].name, *v = &msg->headers[i].value;
mg_str_alloc(&key, *k);
mg_str_alloc(&val, *v);
rpd_keyval_insert(&req->headers, key, val);
}
free(key);
free(val);
free(tmp); free(tmp);
return 0; return 0;
} }
@ -64,7 +80,6 @@ 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