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.
107 lines
2.2 KiB
107 lines
2.2 KiB
2 years ago
|
/* 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_buff_sz(const rpd_res *res);
|
||
|
|
||
|
void rpd_res_init(rpd_res *dest, FCGX_Request *req)
|
||
|
{
|
||
|
dest->out = req->out;
|
||
|
|
||
|
dest->status = rpd_res_st_ok;
|
||
|
dest->location = dest->content_type = NULL;
|
||
|
dest->body = NULL;
|
||
|
|
||
|
rpd_keyval_init(&dest->cookie, 0);
|
||
|
}
|
||
|
|
||
|
int rpd_res_send(rpd_res *res)
|
||
|
{
|
||
|
size_t size = calc_res_buff_sz(res);
|
||
|
|
||
|
char *buff = (char *) malloc(sizeof(char) * size);
|
||
|
if (!buff) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* header */
|
||
|
char *ptr = buff;
|
||
|
ptr += sprintf(ptr, "Status: %d\r\n", res->status);
|
||
|
|
||
|
if (res->content_type) {
|
||
|
ptr += sprintf(ptr, "Content-Type: %s\r\n", res->content_type);
|
||
|
}
|
||
|
|
||
|
if (res->location) {
|
||
|
ptr += sprintf(ptr, "Location: %s\r\n", res->location);
|
||
|
}
|
||
|
|
||
|
memcpy(ptr, "\r\n", 2);
|
||
|
ptr += 2;
|
||
|
|
||
|
/* body */
|
||
|
if (res->body) {
|
||
|
int bodylen = strlen(res->body);
|
||
|
memcpy(ptr, res->body, bodylen);
|
||
|
ptr += bodylen;
|
||
|
}
|
||
|
|
||
|
FCGX_PutS(buff, res->out);
|
||
|
free(buff);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static size_t calc_res_buff_sz(const rpd_res *res)
|
||
|
{
|
||
|
size_t size = res->body ? strlen(res->body) + 2 : 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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size += 2;
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
}
|