refactor: modularize the http header files
							parent
							
								
									89fb77db7f
								
							
						
					
					
						commit
						f07042e798
					
				|  | @ -0,0 +1,46 @@ | ||||||
|  | #ifndef LANDER_HTTP_REQ | ||||||
|  | #define LANDER_HTTP_REQ | ||||||
|  | 
 | ||||||
|  | #include <regex.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | #include "http/types.h" | ||||||
|  | #include "picohttpparser.h" | ||||||
|  | 
 | ||||||
|  | #define HTTP_MAX_ALLOWED_HEADERS 16 | ||||||
|  | #define HTTP_MAX_REGEX_GROUPS 4 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Struct representing the specific type of request | ||||||
|  |  */ | ||||||
|  | typedef struct http_request { | ||||||
|  |   size_t len; | ||||||
|  |   int minor_version; | ||||||
|  |   http_method method; | ||||||
|  |   const char *path; | ||||||
|  |   size_t path_len; | ||||||
|  |   const char *query; | ||||||
|  |   size_t query_len; | ||||||
|  |   http_body_type body_type; | ||||||
|  |   union { | ||||||
|  |     char *buf; | ||||||
|  |     FILE *file; | ||||||
|  |   } body; | ||||||
|  |   size_t body_len; | ||||||
|  |   size_t body_received; | ||||||
|  |   char *body_file_name; | ||||||
|  |   regmatch_t regex_groups[HTTP_MAX_REGEX_GROUPS]; | ||||||
|  |   struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS]; | ||||||
|  |   size_t num_headers; | ||||||
|  | } http_request; | ||||||
|  | 
 | ||||||
|  | typedef enum http_parse_error { | ||||||
|  |   http_parse_error_ok = 0, | ||||||
|  |   http_parse_error_incomplete = 1, | ||||||
|  |   http_parse_error_invalid = 2, | ||||||
|  |   http_parse_error_unknown_method = 3 | ||||||
|  | } http_parse_error; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | #ifndef LANDER_HTTP_RES | ||||||
|  | #define LANDER_HTTP_RES | ||||||
|  | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | #include "http/types.h" | ||||||
|  | 
 | ||||||
|  | typedef struct http_response_header { | ||||||
|  |   http_header type; | ||||||
|  |   const char *value; | ||||||
|  |   bool owned; | ||||||
|  | } http_response_header; | ||||||
|  | 
 | ||||||
|  | typedef struct http_response { | ||||||
|  |   http_status status; | ||||||
|  |   const char *head; | ||||||
|  |   size_t head_len; | ||||||
|  |   size_t head_written; | ||||||
|  |   http_body_type body_type; | ||||||
|  |   union { | ||||||
|  |     char *buf; | ||||||
|  |     FILE *file; | ||||||
|  |   } body; | ||||||
|  |   size_t body_len; | ||||||
|  |   size_t body_written; | ||||||
|  |   // If false, the body won't be freed
 | ||||||
|  |   bool owns_body; | ||||||
|  |   http_response_header headers[4]; | ||||||
|  |   size_t header_count; | ||||||
|  | } http_response; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * 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_res_set_body_buf(http_response *res, const char *body, | ||||||
|  |                            size_t body_len, bool owned); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Set the request body to the given filename. | ||||||
|  |  */ | ||||||
|  | void http_res_set_body_file(http_response *res, const char *filename); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Add a header to the response. | ||||||
|  |  */ | ||||||
|  | void http_res_add_header(http_response *res, http_header type, | ||||||
|  |                          const char *value, bool owned); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Add a Content-Type header corresponding to the mime type. | ||||||
|  |  */ | ||||||
|  | void http_res_set_mime_type(http_response *res, http_mime_type mime_type); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -1,76 +1,24 @@ | ||||||
| #ifndef HTTP | #ifndef LANDER_HTTP_TYPES | ||||||
| #define HTTP | #define LANDER_HTTP_TYPES | ||||||
| 
 | 
 | ||||||
| #include <regex.h> | #include <sys/types.h> | ||||||
| #include <stdbool.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| 
 |  | ||||||
| #include "picohttpparser.h" |  | ||||||
| 
 |  | ||||||
| #define HTTP_MAX_ALLOWED_HEADERS 16 |  | ||||||
| #define HTTP_MAX_REGEX_GROUPS 4 |  | ||||||
| 
 |  | ||||||
| // Array mapping the http_response_type enum to strings
 |  | ||||||
| extern const char *http_response_type_names[][32]; |  | ||||||
| 
 |  | ||||||
| // Array mapping the http_header enum to strings
 |  | ||||||
| extern const char *http_header_names[]; |  | ||||||
| 
 |  | ||||||
| // Array mapping the http_mime_type enum to strings
 |  | ||||||
| extern const char *http_mime_type_names[][2]; |  | ||||||
| 
 | 
 | ||||||
| // Array mapping the http_request_method enum to strings
 | // Array mapping the http_request_method enum to strings
 | ||||||
| extern const char *request_method_names[]; | extern const char *http_method_names[]; | ||||||
| extern const size_t request_method_names_len; | extern const size_t http_method_names_len; | ||||||
| 
 | 
 | ||||||
| typedef enum http_request_method { | typedef enum http_method { | ||||||
|   http_get = 0, |   http_get = 0, | ||||||
|   http_post = 1, |   http_post = 1, | ||||||
|   http_put = 2, |   http_put = 2, | ||||||
|   http_patch = 3, |   http_patch = 3, | ||||||
|   http_delete = 4 |   http_delete = 4 | ||||||
| } http_request_method; | } http_method; | ||||||
| 
 | 
 | ||||||
| typedef enum http_body_type { | // Array mapping the http_response_type enum to strings
 | ||||||
|   http_body_buf = 0, | extern const char *http_status_names[][32]; | ||||||
|   http_body_file = 1 |  | ||||||
| } http_body_type; |  | ||||||
| 
 | 
 | ||||||
| /*
 | typedef enum http_status { | ||||||
|  * Struct representing the specific type of request |  | ||||||
|  */ |  | ||||||
| typedef struct http_request { |  | ||||||
|   size_t len; |  | ||||||
|   int minor_version; |  | ||||||
|   http_request_method method; |  | ||||||
|   const char *path; |  | ||||||
|   size_t path_len; |  | ||||||
|   const char *query; |  | ||||||
|   size_t query_len; |  | ||||||
|   http_body_type body_type; |  | ||||||
|   union { |  | ||||||
|     char *buf; |  | ||||||
|     FILE *file; |  | ||||||
|   } body; |  | ||||||
|   size_t body_len; |  | ||||||
|   size_t body_received; |  | ||||||
|   char *body_file_name; |  | ||||||
|   regmatch_t regex_groups[HTTP_MAX_REGEX_GROUPS]; |  | ||||||
|   struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS]; |  | ||||||
|   size_t num_headers; |  | ||||||
| } http_request; |  | ||||||
| 
 |  | ||||||
| typedef enum http_parse_error { |  | ||||||
|   http_parse_error_ok = 0, |  | ||||||
|   http_parse_error_incomplete = 1, |  | ||||||
|   http_parse_error_invalid = 2, |  | ||||||
|   http_parse_error_unknown_method = 3 |  | ||||||
| } http_parse_error; |  | ||||||
| 
 |  | ||||||
| /* void http_route(event_loop_conn *conn); */ |  | ||||||
| 
 |  | ||||||
| typedef enum http_response_type { |  | ||||||
|   // 1xx
 |   // 1xx
 | ||||||
|   http_continue = 100, |   http_continue = 100, | ||||||
|   http_switching_protocols = 101, |   http_switching_protocols = 101, | ||||||
|  | @ -135,37 +83,10 @@ typedef enum http_response_type { | ||||||
|   http_loop_detected = 508, |   http_loop_detected = 508, | ||||||
|   http_not_extended = 510, |   http_not_extended = 510, | ||||||
|   http_network_authentication_required = 511 |   http_network_authentication_required = 511 | ||||||
| } http_response_type; | } http_status; | ||||||
| 
 | 
 | ||||||
| typedef enum http_header { | // Array mapping the http_mime_type enum to strings
 | ||||||
|   http_header_connection = 0, | extern const char *http_mime_type_names[][2]; | ||||||
|   http_header_location, |  | ||||||
|   http_header_content_type |  | ||||||
| } http_header; |  | ||||||
| 
 |  | ||||||
| typedef struct http_response_header { |  | ||||||
|   http_header type; |  | ||||||
|   const char *value; |  | ||||||
|   bool owned; |  | ||||||
| } http_response_header; |  | ||||||
| 
 |  | ||||||
| typedef struct http_response { |  | ||||||
|   http_response_type status; |  | ||||||
|   const char *head; |  | ||||||
|   size_t head_len; |  | ||||||
|   size_t head_written; |  | ||||||
|   http_body_type body_type; |  | ||||||
|   union { |  | ||||||
|     char *buf; |  | ||||||
|     FILE *file; |  | ||||||
|   } body; |  | ||||||
|   size_t body_len; |  | ||||||
|   size_t body_written; |  | ||||||
|   // If false, the body won't be freed
 |  | ||||||
|   bool owns_body; |  | ||||||
|   http_response_header headers[4]; |  | ||||||
|   size_t header_count; |  | ||||||
| } http_response; |  | ||||||
| 
 | 
 | ||||||
| typedef enum http_mime_type { | typedef enum http_mime_type { | ||||||
|   http_mime_aac = 0, |   http_mime_aac = 0, | ||||||
|  | @ -194,4 +115,18 @@ typedef enum http_mime_type { | ||||||
|   http_mime_7z |   http_mime_7z | ||||||
| } http_mime_type; | } http_mime_type; | ||||||
| 
 | 
 | ||||||
|  | // Array mapping the http_header enum to strings
 | ||||||
|  | extern const char *http_header_names[]; | ||||||
|  | 
 | ||||||
|  | typedef enum http_header { | ||||||
|  |   http_header_connection = 0, | ||||||
|  |   http_header_location, | ||||||
|  |   http_header_content_type | ||||||
|  | } http_header; | ||||||
|  | 
 | ||||||
|  | typedef enum http_body_type { | ||||||
|  |   http_body_buf = 0, | ||||||
|  |   http_body_file = 1 | ||||||
|  | } http_body_type; | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -4,7 +4,9 @@ | ||||||
| #include <regex.h> | #include <regex.h> | ||||||
| 
 | 
 | ||||||
| #include "event_loop.h" | #include "event_loop.h" | ||||||
| #include "http.h" | #include "http/req.h" | ||||||
|  | #include "http/res.h" | ||||||
|  | #include "http/types.h" | ||||||
| #include "trie.h" | #include "trie.h" | ||||||
| 
 | 
 | ||||||
| #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||||||
|  | @ -17,7 +19,7 @@ typedef enum http_route_type { | ||||||
| 
 | 
 | ||||||
| typedef struct http_route { | typedef struct http_route { | ||||||
|   http_route_type type; |   http_route_type type; | ||||||
|   http_request_method method; |   http_method method; | ||||||
|   char *path; |   char *path; | ||||||
|   regex_t *regex; |   regex_t *regex; | ||||||
|   bool (*steps[5])(event_loop_conn *); |   bool (*steps[5])(event_loop_conn *); | ||||||
|  | @ -94,20 +96,6 @@ void http_loop_route_request(event_loop_conn *conn); | ||||||
|  */ |  */ | ||||||
| void http_loop_process_request(event_loop_conn *conn); | 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_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); |  | ||||||
| 
 |  | ||||||
| void http_loop_res_set_mime_type(http_loop_ctx *ctx, http_mime_type mime_type); |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Request step that consumes the request body and stores it in a buffer |  * Request step that consumes the request body and stores it in a buffer | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -1,13 +1,15 @@ | ||||||
| #include "http.h" | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | #include "http/types.h" | ||||||
| 
 | 
 | ||||||
| // Very important that this is in the same order as http_request_method
 | // Very important that this is in the same order as http_request_method
 | ||||||
| const char *request_method_names[] = {"GET", "POST", "PUT", "PATCH", "DELETE"}; | const char *http_method_names[] = {"GET", "POST", "PUT", "PATCH", "DELETE"}; | ||||||
| const size_t request_method_names_len = | const size_t http_method_names_len = | ||||||
|     sizeof(request_method_names) / sizeof(request_method_names[0]); |     sizeof(http_method_names) / sizeof(http_method_names[0]); | ||||||
| 
 | 
 | ||||||
| // clang-format off
 | // clang-format off
 | ||||||
| 
 | 
 | ||||||
| const char *http_response_type_names[][32] = { | const char *http_status_names[][32] = { | ||||||
|   // 1xx
 |   // 1xx
 | ||||||
|   { |   { | ||||||
|     "Continue", // 100
 |     "Continue", // 100
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | #include <sys/stat.h> | ||||||
|  | 
 | ||||||
|  | #include "http/res.h" | ||||||
|  | 
 | ||||||
|  | void http_res_set_body_buf(http_response *res, const char *body, | ||||||
|  |                            size_t body_len, bool owned) { | ||||||
|  |   res->body_type = http_body_buf; | ||||||
|  |   res->body.buf = (char *)body; | ||||||
|  |   res->body_len = body_len; | ||||||
|  |   res->owns_body = owned; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void http_res_set_body_file(http_response *res, const char *filename) { | ||||||
|  |   struct stat st; | ||||||
|  |   stat(filename, &st); | ||||||
|  | 
 | ||||||
|  |   // TODO error handling
 | ||||||
|  |   FILE *f = fopen(filename, "r"); | ||||||
|  | 
 | ||||||
|  |   res->body_type = http_body_file; | ||||||
|  |   res->body.file = f; | ||||||
|  |   res->body_len = st.st_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void http_res_add_header(http_response *res, http_header type, | ||||||
|  |                          const char *value, bool owned) { | ||||||
|  |   res->headers[res->header_count].type = type; | ||||||
|  |   res->headers[res->header_count].value = value; | ||||||
|  |   res->headers[res->header_count].owned = owned; | ||||||
|  | 
 | ||||||
|  |   res->header_count++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void http_res_set_mime_type(http_response *res, http_mime_type mime_type) { | ||||||
|  |   http_res_add_header(res, http_header_content_type, | ||||||
|  |                       http_mime_type_names[mime_type][1], false); | ||||||
|  | } | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| #include <regex.h> | #include <regex.h> | ||||||
| 
 | 
 | ||||||
| #include "http.h" | #include "http/types.h" | ||||||
| #include "http_loop.h" | #include "http_loop.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
| #include "http.h" | #include "http/types.h" | ||||||
| #include "http_loop.h" | #include "http_loop.h" | ||||||
| 
 | 
 | ||||||
| http_loop_gctx *http_loop_gctx_init() { | http_loop_gctx *http_loop_gctx_init() { | ||||||
|  |  | ||||||
|  | @ -34,8 +34,8 @@ http_parse_error http_loop_parse_request(event_loop_conn *conn) { | ||||||
|   bool match = false; |   bool match = false; | ||||||
|   size_t i = 0; |   size_t i = 0; | ||||||
| 
 | 
 | ||||||
|   for (i = 0; i < request_method_names_len; i++) { |   for (i = 0; i < http_method_names_len; i++) { | ||||||
|     if (strncmp(method, request_method_names[i], method_len) == 0) { |     if (strncmp(method, http_method_names[i], method_len) == 0) { | ||||||
|       req->method = i; |       req->method = i; | ||||||
|       match = true; |       match = true; | ||||||
|     } |     } | ||||||
|  | @ -88,7 +88,7 @@ void http_loop_route_request(event_loop_conn *conn) { | ||||||
|   http_loop_ctx *ctx = conn->ctx; |   http_loop_ctx *ctx = conn->ctx; | ||||||
|   http_loop_gctx *gctx = ctx->g; |   http_loop_gctx *gctx = ctx->g; | ||||||
| 
 | 
 | ||||||
|   info("%s %.*s", request_method_names[ctx->req.method], ctx->req.path_len, |   info("%s %.*s", http_method_names[ctx->req.method], ctx->req.path_len, | ||||||
|        ctx->req.path); |        ctx->req.path); | ||||||
| 
 | 
 | ||||||
|   http_route *route; |   http_route *route; | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ void http_loop_init_header(http_response *res) { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const char *response_type_name = |   const char *response_type_name = | ||||||
|       http_response_type_names[res->status / 100 - 1][res->status % 100]; |       http_status_names[res->status / 100 - 1][res->status % 100]; | ||||||
| 
 | 
 | ||||||
|   // First we calculate the size of the start of the header
 |   // First we calculate the size of the start of the header
 | ||||||
|   int buf_size = snprintf(NULL, 0, http_response_format, res->status, |   int buf_size = snprintf(NULL, 0, http_response_format, res->status, | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| #include <sys/stat.h> |  | ||||||
| 
 |  | ||||||
| #include "http_loop.h" |  | ||||||
| 
 |  | ||||||
| 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_body_buf; |  | ||||||
|   ctx->res.body.buf = (char *)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_body_file; |  | ||||||
|   ctx->res.body.file = 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; |  | ||||||
|   ctx->res.headers[ctx->res.header_count].value = value; |  | ||||||
|   ctx->res.headers[ctx->res.header_count].owned = owned; |  | ||||||
| 
 |  | ||||||
|   ctx->res.header_count++; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void http_loop_res_set_mime_type(http_loop_ctx *ctx, http_mime_type mime_type) { |  | ||||||
|   http_loop_res_add_header(ctx, http_header_content_type, |  | ||||||
|                            http_mime_type_names[mime_type][1], false); |  | ||||||
| } |  | ||||||
|  | @ -15,8 +15,8 @@ static 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_buf(ctx, index_page, sizeof(index_page) - 1, false); |   http_res_set_body_buf(&ctx->res, index_page, sizeof(index_page) - 1, false); | ||||||
|   http_loop_res_set_mime_type(ctx, http_mime_html); |   http_res_set_mime_type(&ctx->res, http_mime_html); | ||||||
| 
 | 
 | ||||||
|   conn->state = event_loop_conn_state_res; |   conn->state = event_loop_conn_state_res; | ||||||
|   return true; |   return true; | ||||||
|  | @ -35,12 +35,12 @@ bool lander_get_entry(event_loop_conn *conn) { | ||||||
|     ctx->res.status = http_not_found; |     ctx->res.status = http_not_found; | ||||||
|   } else if (entry->type == Redirect) { |   } else if (entry->type == Redirect) { | ||||||
|     ctx->res.status = http_moved_permanently; |     ctx->res.status = http_moved_permanently; | ||||||
|     http_loop_res_add_header(ctx, http_header_location, entry->string, false); |     http_res_add_header(&ctx->res, http_header_location, entry->string, false); | ||||||
|   } else if (entry->type == Paste) { |   } else if (entry->type == Paste) { | ||||||
|     char fname[8 + key_len]; |     char fname[8 + key_len]; | ||||||
|     sprintf(fname, "pastes/%.*s", key_len, key); |     sprintf(fname, "pastes/%.*s", key_len, key); | ||||||
| 
 | 
 | ||||||
|     http_loop_res_set_body_file(ctx, fname); |     http_res_set_body_file(&ctx->res, fname); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   conn->state = event_loop_conn_state_res; |   conn->state = event_loop_conn_state_res; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | #include "http/res.h" | ||||||
| #include "lander.h" | #include "lander.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +33,7 @@ bool lander_post_redirect(event_loop_conn *conn) { | ||||||
| 
 | 
 | ||||||
|   free(key); |   free(key); | ||||||
| 
 | 
 | ||||||
|   http_loop_res_add_header(ctx, http_header_location, buf, true); |   http_res_add_header(&ctx->res, http_header_location, buf, true); | ||||||
| 
 | 
 | ||||||
|   conn->state = event_loop_conn_state_res; |   conn->state = event_loop_conn_state_res; | ||||||
| 
 | 
 | ||||||
|  | @ -63,7 +64,7 @@ bool lander_post_paste(event_loop_conn *conn) { | ||||||
|   buf[0] = '/'; |   buf[0] = '/'; | ||||||
|   buf[key_len + 1] = '\0'; |   buf[key_len + 1] = '\0'; | ||||||
| 
 | 
 | ||||||
|   http_loop_res_add_header(ctx, http_header_location, buf, true); |   http_res_add_header(&ctx->res, http_header_location, buf, true); | ||||||
| 
 | 
 | ||||||
|   // TODO free this
 |   // TODO free this
 | ||||||
|   char *fname = malloc(8 + key_len); |   char *fname = malloc(8 + key_len); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue