1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#ifndef HTTP_H_
#define HTTP_H_
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
#include "const_strings.h"
#include "arena_strings.h"
#include "arena.h"
typedef struct {
const_string key;
const_string value;
} KV;
typedef struct {
KV *data;
size_t len;
size_t cap;
} header_da;
typedef struct {
const_string key;
const_string val;
} query;
typedef struct {
KV *data;
size_t len;
size_t cap;
} query_da;
struct request {
const_string method;
const_string path;
query_da query;
header_da headers;
const_string body;
};
struct response {
size_t code;
header_da headers;
const_string body;
const_string string;
};
typedef struct {
const_string key;
void *val;
} context_value;
typedef struct {
context_value *data;
size_t len;
size_t cap;
} context;
typedef void (*handler_func)(context*, struct request, struct response *resp);
struct handler {
const_string method;
const_string path;
handler_func func;
};
typedef struct {
struct handler *data;
size_t len;
size_t cap;
} handler_da;
struct server {
int sockfd;
struct sockaddr *addr;
arena *arena;
handler_da handlers;
context global_ctx;
};
typedef enum {
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLY_HINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NO_CONTENT = 204,
MULTIPLE_CHOICES = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
REQUEST_TIMEOUT = 408,
IM_A_TEEPOT = 418,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
HTTP_VERSION_NOT_SUPPPORTED = 505,
} response_code;
const_string get_response_string(response_code code);
void *get_in_addr(struct sockaddr *sa);
int get_in_port(struct sockaddr *sa);
void set_context_value(arena *arena, context *ctx, context_value kv);
void *get_context_value(context *ctx, const_string key);
void resp_set_code(struct response* resp, response_code code);
void resp_set_json(arena *arena, struct response* resp, const_string json);
int init_server(arena *arena, struct server *serv, char *addr, char *port);
int listen_and_serve(struct server *serv);
void handle_path(struct server *serv, const_string method, const_string path, handler_func handler);
#endif // HTTP_H_
|