-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhttp_server.h
126 lines (96 loc) · 2.69 KB
/
http_server.h
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
#ifndef INC_HTTP_SERVER_H_
#define INC_HTTP_SERVER_H_
#if defined( _WIN32 )
#include <WinSock2.h>
typedef SOCKET TSocket;
typedef int socklen_t;
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
typedef int TSocket;
#define closesocket close
#endif
#include <vector>
#include <sys/types.h>
#include <ctime>
#include <string>
namespace HTTP {
// -------------------------------------------------------
struct VBytes : public std::vector<char> {
bool send(TSocket fd) const;
bool recv(TSocket fd);
void format(const char* fmt, ...);
bool read(const char* file);
};
class CBaseServer {
class VSockets : public std::vector<TSocket> {
public:
void remove(TSocket s);
};
public:
// -------------------------------------------------------
struct TRequest {
struct THeaderLine {
const char* title; // 'User-Agent'
const char* value; // 'curl/7.53.0'
};
// only supporting GET
enum eMethod { GET, UNSUPPORTED };
eMethod method;
// / or /index.html...
std::string url;
// Save header lines
static const int max_header_lines = 64;
THeaderLine lines[max_header_lines];
int nlines = 0;
const char* getHeader( const char* title ) const;
bool headerContains(const char* title, const char* text_in_header) const;
std::string getURIParam( const char* title ) const;
std::string getURLPath() const;
bool parse(VBytes& buf, bool trace);
// Who has generated the request
TSocket client;
};
private:
// -------------------------------------------------------
struct TActivity {
fd_set fds;
VSockets ready_to_read;
bool wait(VSockets& sockets, unsigned timeout_usecs);
};
// -------------------------------------------------------
bool createServer(int port);
TSocket acceptNewClient();
void prepare();
// -------------------------
TSocket server;
VSockets active_sockets;
VBytes inbuf;
TActivity activity;
protected:
void sendAnswer(
const TRequest& r
, const VBytes& answer_data
, const char* content_type
, const char* content_encoding = nullptr // gzip, deflate, br or null
);
// Will try to compress your answer automatically if the client suppots compression
void compressAndSendAnswer(
const TRequest& r
, const VBytes& answer_data
, const char* content_type
);
public:
virtual bool onClientRequest(const TRequest& r) = 0;
virtual ~CBaseServer();
bool open(int port);
void close();
// This will block for timeout_usecs at most. 0 just to poll
bool tick(unsigned timeout_usecs);
void runForEver();
bool trace = false;
};
}
#endif