diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml index b6063bb..eaaac5a 100644 --- a/.woodpecker/build.yml +++ b/.woodpecker/build.yml @@ -39,8 +39,7 @@ pipeline: - minio_access_key - minio_secret_key when: - branch: - exclude: [ release/* ] + branch: dev event: push publish-rel: diff --git a/CHANGELOG.md b/CHANGELOG.md index 82b5c0c..d358bd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) +### 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) ### Added diff --git a/include/http/res.h b/include/http/res.h index 6fda002..729958f 100644 --- a/include/http/res.h +++ b/include/http/res.h @@ -24,8 +24,11 @@ typedef struct http_response { size_t head_len; size_t head_written; http_body body; - http_response_header headers[4]; - size_t header_count; + struct { + http_response_header *arr; + size_t len; + size_t cap; + } headers; } http_response; /** diff --git a/src/http/res.c b/src/http/res.c index c3e8806..d965802 100644 --- a/src/http/res.c +++ b/src/http/res.c @@ -1,3 +1,4 @@ +#include #include #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, const char *value, bool owned) { - res->headers[res->header_count].type = type; - res->headers[res->header_count].value = value; - res->headers[res->header_count].owned = owned; + // Extend the header array + if (res->headers.len == res->headers.cap) { + 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) { diff --git a/src/http_loop/http_loop_ctx.c b/src/http_loop/http_loop_ctx.c index 8d0db1e..53a02bf 100644 --- a/src/http_loop/http_loop_ctx.c +++ b/src/http_loop/http_loop_ctx.c @@ -14,6 +14,10 @@ http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g) { ctx->g = g; 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; } @@ -21,6 +25,10 @@ void http_loop_ctx_free(http_loop_ctx *ctx) { http_loop_ctx_reset(ctx); ctx->g->custom_ctx_free(ctx->c); + if (ctx->res.headers.cap > 0) { + free(ctx->res.headers.arr); + } + 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->res.body); - for (size_t i = 0; i < ctx->res.header_count; i++) { - if (ctx->res.headers[i].owned) { - free((void *)ctx->res.headers[i].value); + for (size_t i = 0; i < ctx->res.headers.len; i++) { + if (ctx->res.headers.arr[i].owned) { + 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.head_len = 0; diff --git a/src/http_loop/http_loop_res.c b/src/http_loop/http_loop_res.c index b29550f..5516cb7 100644 --- a/src/http_loop/http_loop_res.c +++ b/src/http_loop/http_loop_res.c @@ -25,10 +25,10 @@ void http_loop_init_header(http_response *res) { response_type_name, res->body.expected_len); // We add each header's required size - for (size_t i = 0; i < res->header_count; i++) { - buf_size += - snprintf(NULL, 0, "%s: %s\n", http_header_names[res->headers[i].type], - res->headers[i].value); + for (size_t i = 0; i < res->headers.len; i++) { + buf_size += snprintf(NULL, 0, "%s: %s\n", + http_header_names[res->headers.arr[i].type], + res->headers.arr[i].value); } // 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, res->body.expected_len); - for (size_t i = 0; i < res->header_count; i++) { - buf_size += - sprintf(&buf[buf_size], "%s: %s\n", - http_header_names[res->headers[i].type], res->headers[i].value); + for (size_t i = 0; i < res->headers.len; i++) { + buf_size += sprintf(&buf[buf_size], "%s: %s\n", + http_header_names[res->headers.arr[i].type], + res->headers.arr[i].value); } buf[buf_size] = '\n';