/** * http.c - Basic HTTP framework implentation * * hashtable.c for routing * listen.c for socket creation * */ #include #include #include #include #include #include "hashtable.h" #include "listen.h" #include "http.h" #define BUF_SIZE 65536 #define HTTP_RES "HTTP/1.1 %d MESSAGE\n"\ "Connection: close\n"\ "Content-Length: %d\n"\ "Content-Type: %s\n"\ "\n"\ "%s" HT* routes; void use(char* path, Handler handler) { if (routes == NULL) { routes = ht_create(); } // TODO: handle for key exist ht_put(routes, path, (void*) handler); } void send_response(int client, Res* res) { char res_raw[BUF_SIZE]; sprintf( res_raw, HTTP_RES, res->status, res->content_length, res->content_type, res->body) ; int num_sent = send(client, res_raw, strlen(res_raw), 0); if (num_sent < 0) { perror("send"); } } void fallback_handler(Res* res) { char* content = "Bad request\n"; res->status = 400; res->content_length = strlen(content); res->content_type = "text/html"; res->body = content; } void parse_req_raw(char* raw, Req* req) { printf("%s\n", raw); sscanf(raw, "%s %s", req->type, req->path); } void handle_request(int client) { char req_raw[BUF_SIZE]; Req req; Res res; int num_recvd = recv(client, req_raw, BUF_SIZE - 1, 0); if (num_recvd < 0) { perror("recv"); return; } parse_req_raw(req_raw, &req); // TODO: handle for parse. printf("Request: %s, %s\n", req.type, req.path); Handler handler = ht_get(routes, req.path); if (handler == NULL) { fallback_handler(&res); } else { handler(&req, &res); } send_response(client, &res); } int http_start(char* port) { int client, server; if ((server = init_server_socket(port)) < 0) { puts("Error when establishing the server."); exit(1); } printf("Waiting for connections on port %s...\n", port); while(1) { client = accept(server, (struct sockaddr*) NULL, NULL); if (client == -1) { perror("accept"); continue; } printf("Client connected.\n"); handle_request(client); close(client); } return 0; }