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