feat(http): allow arbitrary number of response headers
ci/woodpecker/push/build Pipeline was successful Details

lnm
Jef Roosens 2023-11-20 22:25:01 +01:00
parent 4427016094
commit 380605ea08
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
6 changed files with 52 additions and 20 deletions

View File

@ -39,8 +39,7 @@ pipeline:
- minio_access_key - minio_access_key
- minio_secret_key - minio_secret_key
when: when:
branch: branch: dev
exclude: [ release/* ]
event: push event: push
publish-rel: publish-rel:

View File

@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://git.rustybever.be/Chewing_Bever/lander/src/branch/dev) ## [Unreleased](https://git.rustybever.be/Chewing_Bever/lander/src/branch/dev)
### Changed
* HTTP Loop
* Responses can now have an arbitrary number of headers
## [0.2.0](https://git.rustybever.be/Chewing_Bever/lander/src/tag/0.2.0) ## [0.2.0](https://git.rustybever.be/Chewing_Bever/lander/src/tag/0.2.0)
### Added ### Added

View File

@ -24,8 +24,11 @@ typedef struct http_response {
size_t head_len; size_t head_len;
size_t head_written; size_t head_written;
http_body body; http_body body;
http_response_header headers[4]; struct {
size_t header_count; http_response_header *arr;
size_t len;
size_t cap;
} headers;
} http_response; } http_response;
/** /**

View File

@ -1,3 +1,4 @@
#include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "http/res.h" #include "http/res.h"
@ -24,11 +25,25 @@ void http_res_set_body_file(http_response *res, const char *filename) {
void http_res_add_header(http_response *res, http_header type, void http_res_add_header(http_response *res, http_header type,
const char *value, bool owned) { const char *value, bool owned) {
res->headers[res->header_count].type = type; // Extend the header array
res->headers[res->header_count].value = value; if (res->headers.len == res->headers.cap) {
res->headers[res->header_count].owned = owned; http_response_header *new_arr = realloc(
res->headers.arr, 2 * res->headers.cap * sizeof(http_response_header));
res->header_count++; if (new_arr == NULL) {
// TODO error handling
return;
}
res->headers.arr = new_arr;
res->headers.cap *= 2;
}
res->headers.arr[res->headers.len].type = type;
res->headers.arr[res->headers.len].value = value;
res->headers.arr[res->headers.len].owned = owned;
res->headers.len++;
} }
void http_res_set_mime_type(http_response *res, http_mime_type mime_type) { void http_res_set_mime_type(http_response *res, http_mime_type mime_type) {

View File

@ -14,6 +14,10 @@ http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g) {
ctx->g = g; ctx->g = g;
ctx->c = g->custom_ctx_init(); ctx->c = g->custom_ctx_init();
// TODO error checking
ctx->res.headers.arr = malloc(4 * sizeof(http_response_header));
ctx->res.headers.cap = 4;
return ctx; return ctx;
} }
@ -21,6 +25,10 @@ void http_loop_ctx_free(http_loop_ctx *ctx) {
http_loop_ctx_reset(ctx); http_loop_ctx_reset(ctx);
ctx->g->custom_ctx_free(ctx->c); ctx->g->custom_ctx_free(ctx->c);
if (ctx->res.headers.cap > 0) {
free(ctx->res.headers.arr);
}
free(ctx); free(ctx);
} }
@ -36,13 +44,15 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) {
http_body_reset(&ctx->req.body); http_body_reset(&ctx->req.body);
http_body_reset(&ctx->res.body); http_body_reset(&ctx->res.body);
for (size_t i = 0; i < ctx->res.header_count; i++) { for (size_t i = 0; i < ctx->res.headers.len; i++) {
if (ctx->res.headers[i].owned) { if (ctx->res.headers.arr[i].owned) {
free((void *)ctx->res.headers[i].value); free((void *)ctx->res.headers.arr[i].value);
} }
} }
ctx->res.header_count = 0; // We don't set the cap as we can just keep the original array for the next
// requests
ctx->res.headers.len = 0;
ctx->res.status = 0; ctx->res.status = 0;
ctx->res.head_len = 0; ctx->res.head_len = 0;

View File

@ -25,10 +25,10 @@ void http_loop_init_header(http_response *res) {
response_type_name, res->body.expected_len); response_type_name, res->body.expected_len);
// We add each header's required size // We add each header's required size
for (size_t i = 0; i < res->header_count; i++) { for (size_t i = 0; i < res->headers.len; i++) {
buf_size += buf_size += snprintf(NULL, 0, "%s: %s\n",
snprintf(NULL, 0, "%s: %s\n", http_header_names[res->headers[i].type], http_header_names[res->headers.arr[i].type],
res->headers[i].value); res->headers.arr[i].value);
} }
// The + 1 is required to store the final null byte, but we will replace it // The + 1 is required to store the final null byte, but we will replace it
@ -37,10 +37,10 @@ void http_loop_init_header(http_response *res) {
buf_size = sprintf(buf, http_response_format, res->status, response_type_name, buf_size = sprintf(buf, http_response_format, res->status, response_type_name,
res->body.expected_len); res->body.expected_len);
for (size_t i = 0; i < res->header_count; i++) { for (size_t i = 0; i < res->headers.len; i++) {
buf_size += buf_size += sprintf(&buf[buf_size], "%s: %s\n",
sprintf(&buf[buf_size], "%s: %s\n", http_header_names[res->headers.arr[i].type],
http_header_names[res->headers[i].type], res->headers[i].value); res->headers.arr[i].value);
} }
buf[buf_size] = '\n'; buf[buf_size] = '\n';