Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract the request Handler #33

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ OBJS = \
src/models/connection.o \
src/models/session.o \
src/models/post.o \
src/server.o
src/server.o \
src/route.o

deps := $(OBJS:%.o=%.o.d)

Expand Down
26 changes: 26 additions & 0 deletions include/route.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef ROUTE_H
#define ROUTE_H

#include "response.h"
#include "request.h"

typedef enum ROUTE_MATCH {
NONE, EXACT, NORMAL
} ROUTE_MATCH;

typedef Response *(*Handler)(Request *);
typedef Response *(**HandlerP)(Request *);

typedef struct Route {
const char * path;
ROUTE_MATCH match;

Handler handler;
} Route;

Route *routeNew(Handler handler);
void routeDel(Route *);
Response *routeHandle(Route *, Request *);
void routeAddPath(Route *, ROUTE_MATCH match, const char *);

#endif
7 changes: 4 additions & 3 deletions include/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
#include "list.h"
#include "request.h"
#include "response.h"
#include "route.h"

typedef struct Server {
unsigned int port;

ListCell *handlers;
ListCell *routes;
} Server;

typedef Response *(*Handler)(Request *);
typedef Response *(**HandlerP)(Request *);

Server *serverNew(unsigned int);
void serverDel(Server *);
void serverAddHandler(Server *, Handler);
void serverAddStaticHandler(Server *);
Route *serverAddRoute(Server *, ROUTE_MATCH, const char *, Handler);
void serverAddStaticRoute(Server *, ROUTE_MATCH, const char *);
void serverServe(Server *);

#endif
52 changes: 15 additions & 37 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,21 @@ int main(int argc, char *argv[])
}
}
Server *server = serverNew(server_port);
serverAddHandler(server, notFound);
serverAddStaticHandler(server);
serverAddHandler(server, about);
serverAddHandler(server, signup);
serverAddHandler(server, logout);
serverAddHandler(server, login);
serverAddHandler(server, search);
serverAddHandler(server, connect);
serverAddHandler(server, like);
serverAddHandler(server, unlike);
serverAddHandler(server, post);
serverAddHandler(server, profile);
serverAddHandler(server, dashboard);
serverAddHandler(server, home);
serverAddHandler(server, session);
serverAddRoute(server, NONE, NULL, notFound);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you think of the better way to decouple the following routing rules from main function? I expect the modularized URI handlers can be maintained without the hooks in main function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean separate the handler to another file?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the design is intended to work with FastCGI model later: http://kristaps.bsd.lv/kcgi/
We should eliminate the dependency of given route handlers in main module.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is beyond my knowledge, I have no idea how to modify

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead, you can split the handler in a dedicated routine as cgi_url_dltrie.c does.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I'll try to modify it, and notice you when it's done

serverAddStaticRoute(server, NORMAL, "/static/");
serverAddRoute(server, EXACT, "/about/", about);
serverAddRoute(server, EXACT, "/signup/", signup);
serverAddRoute(server, EXACT, "/logout/", logout);
serverAddRoute(server, EXACT, "/login/", login);
serverAddRoute(server, EXACT, "/search/", search);
serverAddRoute(server, NORMAL, "/connect/", connect);
serverAddRoute(server, NORMAL, "/like/", like);
serverAddRoute(server, NORMAL, "/unlike/", unlike);
serverAddRoute(server, EXACT, "/post/", post);
serverAddRoute(server, NORMAL, "/profile/", profile);
serverAddRoute(server, EXACT, "/dashboard/", dashboard);
serverAddRoute(server, EXACT, "/", home);
serverAddRoute(server, NONE, NULL, session);
serverServe(server);

return 0;
Expand All @@ -158,8 +158,6 @@ static Response *session(Request *req)

static Response *home(Request *req)
{
EXACT_ROUTE(req, "/");

if (req->account)
return responseNewRedirect("/dashboard/");

Expand All @@ -175,8 +173,6 @@ static Response *home(Request *req)

static Response *dashboard(Request *req)
{
EXACT_ROUTE(req, "/dashboard/");

if (!req->account)
return responseNewRedirect("/login/");

Expand Down Expand Up @@ -256,8 +252,6 @@ static Response *dashboard(Request *req)

static Response *profile(Request *req)
{
ROUTE(req, "/profile/");

if (!req->account) return NULL;

int id = -1;
Expand Down Expand Up @@ -360,8 +354,6 @@ static Response *profile(Request *req)

static Response *post(Request *req)
{
EXACT_ROUTE(req, "/post/");

if (req->method != POST) return NULL;

char *postStr = kvFindList(req->postBody, "post");
Expand All @@ -376,8 +368,6 @@ static Response *post(Request *req)

static Response *unlike(Request *req)
{
ROUTE(req, "/unlike/");

if (!req->account) return NULL;

int id = -1;
Expand Down Expand Up @@ -405,8 +395,6 @@ static Response *unlike(Request *req)

static Response *like(Request *req)
{
ROUTE(req, "/like/");

if (!req->account) return NULL;

int id = -1;
Expand Down Expand Up @@ -434,7 +422,6 @@ static Response *like(Request *req)

static Response *connect(Request *req)
{
ROUTE(req, "/connect/");
if (!req->account) return NULL;

int id = -1;
Expand All @@ -460,8 +447,6 @@ static Response *connect(Request *req)

static Response *search(Request *req)
{
EXACT_ROUTE(req, "/search/");

if (!req->account)
return responseNewRedirect("/login/");

Expand Down Expand Up @@ -521,8 +506,6 @@ static Response *search(Request *req)

static Response *login(Request *req)
{
EXACT_ROUTE(req, "/login/");

if (req->account)
return responseNewRedirect("/dashboard/");

Expand Down Expand Up @@ -571,7 +554,6 @@ static Response *login(Request *req)

static Response *logout(Request *req)
{
EXACT_ROUTE(req, "/logout/");
if (!req->account)
return responseNewRedirect("/");

Expand All @@ -582,8 +564,6 @@ static Response *logout(Request *req)

static Response *signup(Request *req)
{
EXACT_ROUTE(req, "/signup/");

if (req->account)
return responseNewRedirect("/dashboard/");

Expand Down Expand Up @@ -672,8 +652,6 @@ static Response *signup(Request *req)

static Response *about(Request *req)
{
EXACT_ROUTE(req, "/about/");

Response *response = responseNew();
Template *template = templateNew("templates/about.html");
templateSet(template, "active", "about");
Expand Down
46 changes: 46 additions & 0 deletions src/route.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "route.h"

Route *routeNew(Handler handler)
{
Route *route = malloc(sizeof(Route));
route->path = NULL;
route->match = NONE;
route->handler = handler;
return route;
}

void routeDel(Route *route)
{
free(route);
}

Response *routeHandle(Route *route, Request * req)
{
if (route->path) {
switch (route->match) {
case EXACT:
if (strcmp(req->uri, route->path) != 0)
return NULL;
break;
case NORMAL:
if (strncmp(req->uri, route->path, strlen(route->path)) != 0)
return NULL;
break;
default:
break;
}
}

return route->handler(req);
}

void routeAddPath(Route *route, ROUTE_MATCH match, const char *path)
{
route->path = path;
route->match = match;
}
26 changes: 15 additions & 11 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,28 @@ Server *serverNew(unsigned int port)
{
Server *server = malloc(sizeof(Server));
server->port = port;
server->handlers = NULL;
server->routes = NULL;
return server;
}

void serverDel(Server *server)
{
if (server->handlers) listDel(server->handlers);
if (server->routes) listDel(server->routes);
free(server);

#ifdef _WIN32
WSACleanup();
#endif
}

void serverAddHandler(Server *server, Handler handler)
Route *serverAddRoute(Server *server, ROUTE_MATCH match, const char *path, Handler handler)
{
HandlerP handlerP = &handler;
server->handlers = listCons(handlerP, sizeof(HandlerP), server->handlers);
Route * route = routeNew(handler);
routeAddPath(route, match, path);

server->routes = listCons(route, sizeof(Route), server->routes);

return (Route *)(server->routes->value);
}

static Response *staticHandler(Request *req)
Expand Down Expand Up @@ -144,9 +148,9 @@ static Response *staticHandler(Request *req)
return response;
}

void serverAddStaticHandler(Server *server)
void serverAddStaticRoute(Server *server, ROUTE_MATCH match, const char * path)
{
serverAddHandler(server, staticHandler);
serverAddRoute(server, match, path, staticHandler);
}

static inline int makeSocket(unsigned int port)
Expand Down Expand Up @@ -198,12 +202,12 @@ static inline void handle(Server *server, int fd, fd_set *activeFDs, struct sock
send(fd, "HTTP/1.0 400 Bad Request\r\n\r\nBad Request", 39, 0);
LOG_400(addr);
} else {
ListCell *handler = server->handlers;
ListCell *route = server->routes;
Response *response = NULL;

while (handler && !response) {
response = (*(HandlerP)handler->value)(req);
handler = handler->next;
while (route && !response) {
response = routeHandle((Route *)(route->value), req);
route = route->next;
}

if (!response) {
Expand Down