1818
1919using namespace std ;
2020
21+ class NotFoundHandler : public RequestHandler {
22+ string notFoundErrPage;
23+
24+ public:
25+ NotFoundHandler (string notFoundErrPage = " " )
26+ : notFoundErrPage(notFoundErrPage) {}
27+ Response *callback (Request *req) {
28+ Response *res = new Response (404 );
29+ if (!notFoundErrPage.empty ()) {
30+ res->setHeader (" Content-Type" , " text/" + getExtension (notFoundErrPage));
31+ res->setBody (readFile (notFoundErrPage.c_str ()));
32+ }
33+ return res;
34+ }
35+ };
36+
37+ class ServerErrorHandler {
38+ public:
39+ static Response *callback (string msg) {
40+ Response *res = new Response (500 );
41+ res->setHeader (" Content-Type" , " application/json" );
42+ res->setBody (" { \" code\" : \" 500\" , \" message\" : \" " + msg + " \" }\n " );
43+ return res;
44+ }
45+ };
46+
2147void split (string str, string separator, int max, vector<string> &results) {
2248 int i = 0 ;
2349 size_t found = str.find_first_of (separator);
@@ -174,7 +200,9 @@ Request *parseRawReq(char *headersRaw) {
174200 return req;
175201}
176202
177- Server::Server (int _port) : port(_port), notFoundHandler(NULL ) {
203+ Server::Server (int _port) : port(_port) {
204+ notFoundHandler = new NotFoundHandler ();
205+
178206 sc = socket (AF_INET, SOCK_STREAM, 0 );
179207 int sc_option = 1 ;
180208 setsockopt (sc, SOL_SOCKET, SO_REUSEADDR, &sc_option, sizeof (sc_option));
@@ -202,19 +230,6 @@ void Server::post(string path, RequestHandler *handler) {
202230 routes.push_back (route);
203231}
204232
205- class NotFoundHandler : public RequestHandler {
206- string notFoundErrPage;
207-
208- public:
209- NotFoundHandler (string notFoundErrPage) : notFoundErrPage(notFoundErrPage) {}
210- Response *callback (Request *req) {
211- Response *res = new Response (404 );
212- res->setHeader (" Content-Type" , " text/" + getExtension (notFoundErrPage));
213- res->setBody (readFile (notFoundErrPage.c_str ()));
214- return res;
215- }
216- };
217-
218233void Server::run () {
219234 ::listen (sc, 10 );
220235
@@ -227,37 +242,42 @@ void Server::run() {
227242 newsc = ::accept (sc, (struct sockaddr *)&cli_addr, &clilen);
228243 if (newsc < 0 )
229244 throw Exception (" Error on accept: " + string (strerror (errno)));
230-
231- char data[BUFSIZE + 1 ];
232- size_t recv_len, recv_total_len = 0 ;
233- Request *req = NULL ;
234- while (!req) {
235- recv_len =
236- recv (newsc, data + recv_total_len, BUFSIZE - recv_total_len, 0 );
237- if (recv_len > 0 ) {
238- recv_total_len += recv_len;
239- data[recv_total_len >= 0 ? recv_total_len : 0 ] = 0 ;
240- req = parseRawReq (data);
241- } else
242- break ;
243- }
244- if (!recv_total_len) {
245- ::close (newsc);
246- continue ;
247- }
248- req->log ();
249- Response *res = new Response ();
250- size_t i = 0 ;
251- for (; i < routes.size (); i++) {
252- if (routes[i]->isMatch (req->getMethod (), req->getPath ())) {
253- res = routes[i]->handle (req);
254- break ;
245+ Response *res = NULL ;
246+ try {
247+ char data[BUFSIZE + 1 ];
248+ size_t recv_len, recv_total_len = 0 ;
249+ Request *req = NULL ;
250+ while (!req) {
251+ recv_len =
252+ recv (newsc, data + recv_total_len, BUFSIZE - recv_total_len, 0 );
253+ if (recv_len > 0 ) {
254+ recv_total_len += recv_len;
255+ data[recv_total_len >= 0 ? recv_total_len : 0 ] = 0 ;
256+ req = parseRawReq (data);
257+ } else
258+ break ;
255259 }
260+ if (!recv_total_len) {
261+ ::close (newsc);
262+ continue ;
263+ }
264+ req->log ();
265+ res = new Response ();
266+ size_t i = 0 ;
267+ for (; i < routes.size (); i++) {
268+ if (routes[i]->isMatch (req->getMethod (), req->getPath ())) {
269+ res = routes[i]->handle (req);
270+ break ;
271+ }
272+ }
273+ if (i == routes.size () && notFoundHandler) {
274+ res = notFoundHandler->callback (req);
275+ }
276+ delete req;
277+ } catch (Exception exc) {
278+ delete res;
279+ res = ServerErrorHandler::callback (exc.getMessage ());
256280 }
257- if (i == routes.size () && notFoundHandler) {
258- res = notFoundHandler->callback (req);
259- }
260- delete req;
261281 int si;
262282 res->log ();
263283 string res_data = res->print (si);
0 commit comments