feat: start of http part of server
parent
6d45ec59dc
commit
c58e53eb2a
|
@ -4,3 +4,4 @@ compile_commands.json
|
||||||
# Data files
|
# Data files
|
||||||
lander.data
|
lander.data
|
||||||
pastes/
|
pastes/
|
||||||
|
.cache/
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef HTTP
|
||||||
|
#define HTTP
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern const char http_404[];
|
||||||
|
extern const size_t http_404_len;
|
||||||
|
extern const char http_500[];
|
||||||
|
extern const size_t http_500_len;
|
||||||
|
|
||||||
|
typedef enum http_request_entity {
|
||||||
|
event_loop_request_type_unknown = 0
|
||||||
|
} http_request_entity;
|
||||||
|
|
||||||
|
typedef enum http_request_method {
|
||||||
|
http_request_method_get = 0,
|
||||||
|
http_request_method_post = 1,
|
||||||
|
http_request_method_put = 2,
|
||||||
|
http_request_method_patch = 3,
|
||||||
|
http_request_method_delete = 4
|
||||||
|
} http_request_method;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct representing the specific type of request
|
||||||
|
*/
|
||||||
|
typedef struct http_request {
|
||||||
|
http_request_method type;
|
||||||
|
http_request_entity entity;
|
||||||
|
} 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;
|
||||||
|
|
||||||
|
http_parse_error http_parse_request(http_request *req, const char *path, size_t path_len);
|
||||||
|
|
||||||
|
#endif
|
|
@ -74,34 +74,31 @@ bool event_loop_handle_request(event_loop_conn *conn) {
|
||||||
&minor_version, headers, &num_headers, 0);
|
&minor_version, headers, &num_headers, 0);
|
||||||
|
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
/* conn->close_after_write = true; */
|
/* for (size_t i = 0; i < num_headers; i++) { */
|
||||||
// TODO allow HTTP pipelining
|
/* /1* printf("%.*s: ", headers[i].name_len, headers[i].name); *1/ */
|
||||||
/* conn->close_after_write = true; */
|
/* /1* printf("%.*s\n", headers[i].value_len, headers[i].value); *1/ */
|
||||||
for (int i = 0; i < num_headers; i++) {
|
/* if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) { */
|
||||||
/* printf("%.*s: ", headers[i].name_len, headers[i].name); */
|
/* if (strncmp("close", headers[i].value, headers[i].value_len) == 0) { */
|
||||||
/* printf("%.*s\n", headers[i].value_len, headers[i].value); */
|
/* conn->close_after_write = true; */
|
||||||
if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) {
|
/* break; */
|
||||||
if (strncmp("close", headers[i].value, headers[i].value_len) == 0) {
|
/* } */
|
||||||
conn->close_after_write = true;
|
/* } */
|
||||||
break;
|
/* } */
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(conn->wbuf, http_200_ok, sizeof(http_200_ok) - 1);
|
/* memcpy(conn->wbuf, http_500, http_500_len); */
|
||||||
|
|
||||||
// Move the new request up to the front of the read buffer
|
/* // Move the new request up to the front of the read buffer */
|
||||||
memmove(conn->rbuf, &conn->rbuf[res], conn->rbuf_size - res);
|
/* memmove(conn->rbuf, &conn->rbuf[res], conn->rbuf_size - res); */
|
||||||
conn->rbuf_size -= res;
|
/* conn->rbuf_size -= res; */
|
||||||
|
|
||||||
conn->state = event_loop_conn_state_res;
|
/* conn->state = event_loop_conn_state_res; */
|
||||||
conn->wbuf_size = sizeof(http_200_ok) - 1;
|
/* conn->wbuf_size = http_500_len; */
|
||||||
conn->wbuf_sent = 0;
|
/* conn->wbuf_sent = 0; */
|
||||||
|
|
||||||
event_loop_conn_io_res(conn);
|
/* /1* event_loop_conn_io_res(conn); *1/ */
|
||||||
|
|
||||||
// End the connection if the http request is invalid, or when the response
|
/* // End the connection if the http request is invalid, or when the response */
|
||||||
// is too large to fit into a single read buffer
|
/* // is too large to fit into a single read buffer */
|
||||||
} else if (res == -1 ||
|
} else if (res == -1 ||
|
||||||
(res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) {
|
(res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) {
|
||||||
conn->state = event_loop_conn_state_end;
|
conn->state = event_loop_conn_state_end;
|
||||||
|
|
|
@ -53,9 +53,4 @@ int event_loop_accept(event_loop *loop, int fd);
|
||||||
|
|
||||||
void event_loop_conn_io(event_loop_conn *conn);
|
void event_loop_conn_io(event_loop_conn *conn);
|
||||||
|
|
||||||
extern const char http_404[];
|
|
||||||
extern const size_t http_404_len;
|
|
||||||
extern const char http_500[];
|
|
||||||
extern const size_t http_500_len;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <stdlib.h>
|
#include "http.h"
|
||||||
|
|
||||||
const char http_404[] = "HTTP/1.1 404 Not Found\n"
|
const char http_404[] = "HTTP/1.1 404 Not Found\n"
|
||||||
"Connection: close\n"
|
"Connection: close\n"
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include "http.h"
|
||||||
|
#include "picohttpparser.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* given the HTTP path, parse the request
|
||||||
|
*/
|
||||||
|
http_parse_error http_parse_request(http_request *req, const char *buf, size_t buf_size) {
|
||||||
|
// First we try to parse the incoming HTTP request
|
||||||
|
const char *method, *path;
|
||||||
|
struct phr_header headers[16];
|
||||||
|
size_t method_len, path_len, num_headers;
|
||||||
|
int minor_version;
|
||||||
|
|
||||||
|
int res = phr_parse_request(buf, buf_size,
|
||||||
|
&method, &method_len, &path, &path_len,
|
||||||
|
&minor_version, headers, &num_headers, 0);
|
||||||
|
|
||||||
|
if (res == -2) {
|
||||||
|
return http_parse_error_incomplete;
|
||||||
|
} else if (res < 0) {
|
||||||
|
return http_parse_error_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, we parse the HTTP request as a lander-specific request
|
||||||
|
if (path_len == 0 || path[0] != '/') {
|
||||||
|
return http_parse_error_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return http_parse_error_ok;
|
||||||
|
}
|
Loading…
Reference in New Issue