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,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); | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| #include <stdio.h> | ||||
| 
 | ||||
| #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; | ||||
|  |  | |||
|  | @ -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); | ||||
|     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; | ||||
|  |  | |||
|  | @ -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