137 lines
2.4 KiB
C
137 lines
2.4 KiB
C
/**
|
|
* http.c - Basic HTTP framework implentation
|
|
*
|
|
* hashtable.c for routing
|
|
* listen.c for socket creation
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
|
|
#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;
|
|
}
|