feat: support serving files
parent
34ecb7eb40
commit
095f86ad72
|
@ -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
|
||||
|
|
|
@ -94,9 +94,11 @@ 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,
|
||||
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);
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "http.h"
|
||||
#include "http_loop.h"
|
||||
|
||||
|
@ -29,9 +31,15 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) {
|
|||
ctx->res.head = NULL;
|
||||
}
|
||||
|
||||
if (ctx->res.owns_body && ctx->res.body != NULL) {
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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);
|
||||
size_t bytes_written;
|
||||
|
||||
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,
|
||||
void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body,
|
||||
size_t body_len, bool owned) {
|
||||
ctx->res.body = body;
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue