feat: support serving files
parent
34ecb7eb40
commit
095f86ad72
|
@ -126,12 +126,18 @@ typedef struct http_response_header {
|
||||||
bool owned;
|
bool owned;
|
||||||
} http_response_header;
|
} 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 {
|
typedef struct http_response {
|
||||||
http_response_type type;
|
http_response_type type;
|
||||||
const char *head;
|
const char *head;
|
||||||
size_t head_len;
|
size_t head_len;
|
||||||
size_t head_written;
|
size_t head_written;
|
||||||
const char *body;
|
http_response_body_type body_type;
|
||||||
|
void *body;
|
||||||
size_t body_len;
|
size_t body_len;
|
||||||
size_t body_written;
|
size_t body_written;
|
||||||
// If false, the body won't be freed
|
// 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
|
* 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.
|
* 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);
|
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,
|
void http_loop_res_add_header(http_loop_ctx *ctx, http_header type,
|
||||||
const char *value, bool owned);
|
const char *value, bool owned);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "http_loop.h"
|
#include "http_loop.h"
|
||||||
|
|
||||||
|
@ -29,9 +31,15 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) {
|
||||||
ctx->res.head = NULL;
|
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);
|
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++) {
|
for (size_t i = 0; i < ctx->res.header_count; i++) {
|
||||||
if (ctx->res.headers[i].owned) {
|
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.header_count = 0;
|
||||||
|
|
||||||
ctx->res.body = NULL;
|
|
||||||
|
|
||||||
ctx->res.type = 0;
|
ctx->res.type = 0;
|
||||||
ctx->res.head_len = 0;
|
ctx->res.head_len = 0;
|
||||||
ctx->res.head_written = 0;
|
ctx->res.head_written = 0;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "http_loop.h"
|
#include "http_loop.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -82,21 +83,45 @@ void http_loop_write_response(event_loop_conn *conn) {
|
||||||
if (res->body_written < res->body_len) {
|
if (res->body_written < res->body_len) {
|
||||||
size_t bytes_to_write = MIN(res->body_len - res->body_written,
|
size_t bytes_to_write = MIN(res->body_len - res->body_written,
|
||||||
EVENT_LOOP_BUFFER_SIZE - conn->wbuf_size);
|
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],
|
memcpy(&conn->wbuf[conn->wbuf_size], &res->body[res->body_written],
|
||||||
bytes_to_write);
|
bytes_to_write);
|
||||||
|
|
||||||
conn->wbuf_size += bytes_to_write;
|
conn->wbuf_size += bytes_to_write;
|
||||||
res->body_written += 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) {
|
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.body_len = body_len;
|
||||||
ctx->res.owns_body = owned;
|
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,
|
void http_loop_res_add_header(http_loop_ctx *ctx, http_header type,
|
||||||
const char *value, bool owned) {
|
const char *value, bool owned) {
|
||||||
ctx->res.headers[ctx->res.header_count].type = type;
|
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) {
|
bool lander_get_index(event_loop_conn *conn) {
|
||||||
http_loop_ctx *ctx = conn->ctx;
|
http_loop_ctx *ctx = conn->ctx;
|
||||||
|
|
||||||
http_loop_res_set_body(ctx, index_page, sizeof(index_page) - 1, false);
|
http_loop_res_set_body_file(ctx, "Dockerfile");
|
||||||
http_loop_res_add_header(ctx, http_header_connection, "close", false);
|
|
||||||
|
|
||||||
conn->state = event_loop_conn_state_res;
|
conn->state = event_loop_conn_state_res;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue