C and C++ web framework. http://rapida.vilor.one/docs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

127 lines
2.7 KiB

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2022 Ivan Polyakov */
#include "response.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static size_t calc_res_headers_sz(const rpd_res *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);
}
int rpd_res_headers_str(char **dest, const rpd_res *src)
{
size_t size = calc_res_headers_sz(src);
char *ptr;
*dest = (char *) malloc(sizeof(char) * size);
if (!*dest) {
perror("malloc");
return 1;
}
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);
}
return 0;
}
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);
if (res->body)
size += 2 + strlen(res->body);
*dest = (char *) malloc(sizeof(char) * size);
if (!*dest) {
perror("malloc");
return 1;
}
/* header */
ptr = *dest;
ptr += sprintf(ptr, "Status: %d\r\n", res->status);
if (rpd_res_headers_str(&headers, res)) {
return 1;
}
memcpy(ptr, headers, headers_size);
free(headers);
ptr += headers_size;
memcpy(ptr, "\r\n", 2);
ptr += 2;
/* body */
if (res->body) {
int bodylen = strlen(res->body);
memcpy(ptr, res->body, bodylen);
ptr += bodylen;
}
return 0;
}
static size_t calc_res_headers_sz(const rpd_res *res)
{
size_t size = 0;
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);
}
}
return size;
}
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);
}
}