diff --git a/include/http.h b/include/http.h index f20678f..6a7c3f9 100644 --- a/include/http.h +++ b/include/http.h @@ -126,12 +126,18 @@ typedef struct http_response_header { bool owned; } http_response_header; +typedef enum http_response_body_type { + http_response_body_buf = 0, + http_response_body_file = 1 +} http_response_body_type; + typedef struct http_response { http_response_type type; const char *head; size_t head_len; size_t head_written; - const char *body; + http_response_body_type body_type; + void *body; size_t body_len; size_t body_written; // If false, the body won't be freed diff --git a/include/http_loop.h b/include/http_loop.h index eee2f6c..e2872c1 100644 --- a/include/http_loop.h +++ b/include/http_loop.h @@ -94,8 +94,10 @@ void http_loop_process_request(event_loop_conn *conn); * Set the request body to the given buffer. If owned is set to true, the body * buffer will be free'd after the request has finished. */ -void http_loop_res_set_body(http_loop_ctx *ctx, const char *body, - size_t body_len, bool owned); +void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body, + size_t body_len, bool owned); + +void http_loop_res_set_body_file(http_loop_ctx *ctx, const char *filename); void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, const char *value, bool owned); diff --git a/src/http_loop/http_loop_ctx.c b/src/http_loop/http_loop_ctx.c index 39fdc16..1573c35 100644 --- a/src/http_loop/http_loop_ctx.c +++ b/src/http_loop/http_loop_ctx.c @@ -1,3 +1,5 @@ +#include + #include "http.h" #include "http_loop.h" @@ -29,10 +31,16 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) { ctx->res.head = NULL; } - if (ctx->res.owns_body && ctx->res.body != NULL) { - free((void *)ctx->res.body); + if (ctx->res.body != NULL) { + if (ctx->res.body_type == http_response_body_buf && ctx->res.owns_body) { + free((void *)ctx->res.body); + } else if (ctx->res.body_type == http_response_body_file) { + fclose(ctx->res.body); + } } + ctx->res.body = NULL; + for (size_t i = 0; i < ctx->res.header_count; i++) { if (ctx->res.headers[i].owned) { free((void *)ctx->res.headers[i].value); @@ -41,8 +49,6 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) { ctx->res.header_count = 0; - ctx->res.body = NULL; - ctx->res.type = 0; ctx->res.head_len = 0; ctx->res.head_written = 0; diff --git a/src/http_loop/http_loop_res.c b/src/http_loop/http_loop_res.c index 104272a..0305f6f 100644 --- a/src/http_loop/http_loop_res.c +++ b/src/http_loop/http_loop_res.c @@ -1,4 +1,5 @@ #include +#include #include "http_loop.h" #include "log.h" @@ -82,21 +83,45 @@ void http_loop_write_response(event_loop_conn *conn) { if (res->body_written < res->body_len) { size_t bytes_to_write = MIN(res->body_len - res->body_written, EVENT_LOOP_BUFFER_SIZE - conn->wbuf_size); - memcpy(&conn->wbuf[conn->wbuf_size], &res->body[res->body_written], - bytes_to_write); + size_t bytes_written; - conn->wbuf_size += bytes_to_write; - res->body_written += bytes_to_write; + switch (res->body_type) { + case http_response_body_buf: + memcpy(&conn->wbuf[conn->wbuf_size], &res->body[res->body_written], + bytes_to_write); + conn->wbuf_size += bytes_to_write; + res->body_written += bytes_to_write; + break; + case http_response_body_file: + bytes_written = fread(&conn->wbuf[conn->wbuf_size], sizeof(uint8_t), + bytes_to_write, res->body); + conn->wbuf_size += bytes_written; + res->body_written += bytes_written; + break; + } } } -void http_loop_res_set_body(http_loop_ctx *ctx, const char *body, - size_t body_len, bool owned) { - ctx->res.body = body; +void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body, + size_t body_len, bool owned) { + ctx->res.body_type = http_response_body_buf; + ctx->res.body = (void *)body; ctx->res.body_len = body_len; ctx->res.owns_body = owned; } +void http_loop_res_set_body_file(http_loop_ctx *ctx, const char *filename) { + struct stat st; + stat(filename, &st); + + // TODO error handling + FILE *f = fopen(filename, "r"); + + ctx->res.body_type = http_response_body_file; + ctx->res.body = f; + ctx->res.body_len = st.st_size; +} + void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, const char *value, bool owned) { ctx->res.headers[ctx->res.header_count].type = type; diff --git a/src/main.c b/src/main.c index d96a0b3..99ca6c8 100644 --- a/src/main.c +++ b/src/main.c @@ -17,8 +17,7 @@ const char index_page[] = bool lander_get_index(event_loop_conn *conn) { http_loop_ctx *ctx = conn->ctx; - http_loop_res_set_body(ctx, index_page, sizeof(index_page) - 1, false); - http_loop_res_add_header(ctx, http_header_connection, "close", false); + http_loop_res_set_body_file(ctx, "Dockerfile"); conn->state = event_loop_conn_state_res;