Browse Source

added a generic router. This is a REST router that maps urls to specific functions which it tries to find via dlsym. That way the only thing to do to get a new REST functionality is to add a function that fits into the namesheme. All existing functionality is moved accordingly

v0.1.8
Georg Hopp 12 years ago
parent
commit
a1350d7591
  1. 14
      assets/js/init.js
  2. 1
      configure.ac
  3. 2
      include/application/adapter/http.h
  4. 17
      include/http/request.h
  5. 59
      include/router.h
  6. 11
      src/Makefile.am
  7. 9
      src/application/Makefile.am
  8. 2
      src/application/adapter/http/http.c
  9. 245
      src/application/adapter/http/update.c
  10. 75
      src/application/controller/authenticate/create.c
  11. 44
      src/application/controller/authenticate/delete.c
  12. 58
      src/application/controller/currentuser/read.c
  13. 63
      src/application/controller/randval/read.c
  14. 59
      src/application/controller/sessinfo/read.c
  15. 98
      src/application/controller/user/create.c
  16. 49
      src/application/controller/version/read.c
  17. 2
      src/http/Makefile.am
  18. 12
      src/http/request.c
  19. 15
      src/http/request/get_method_id.c
  20. 11
      src/router/Makefile.am
  21. 181
      src/router/route.c
  22. 66
      src/router/router.c
  23. 5
      src/taskrambler.c

14
assets/js/init.js

@ -46,21 +46,27 @@ $(document).ready(function() {
);
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
$.getJSON("/user/get/", $.proxy(sess.loadUserJSON, sess));
$.getJSON("/currentuser/", $.proxy(sess.loadUserJSON, sess));
$(window).focus(function() {
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
});
$("div#menu ul li.logout").click(function() {
$.getJSON("/logout/", $.proxy(sess.loadUserJSON, sess));
$.ajax({
dataType: "json",
url: "/authenticate/",
type: 'DELETE',
success: $.proxy(sess.loadUserJSON, sess)
});
//$.getJSON("/authenticate/", $.proxy(sess.loadUserJSON, sess));
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
});
$("#login").load("/_login.html", function (){
$("#login form").submit(function(event) {
event.preventDefault();
$.post("/login/",
$.post("/authenticate/",
$("#login form").serialize(),
$.proxy(sess.loadUserJSON, sess));
$("#login").addClass("hide");
@ -71,7 +77,7 @@ $(document).ready(function() {
$("#signup").load("/_signup.html", function (){
$("#signup form").submit(function(event) {
event.preventDefault();
$.post("/signup/",
$.post("/user/",
$("#signup form").serialize(),
$.proxy(sess.loadUserJSON, sess));
$("#signup").addClass("hide");

1
configure.ac

@ -97,6 +97,7 @@ AC_CONFIG_FILES([Makefile
src/storage/Makefile
src/user/Makefile
src/config/Makefile
src/router/Makefile
docs/Makefile
config/Makefile
tests/Makefile])

2
include/application/adapter/http.h

@ -24,11 +24,13 @@
#define __APPLICATION_ADAPTER_HTTP_H__
#include "class.h"
#include "router.h"
#include "application/application.h"
CLASS(ApplicationAdapterHttp) {
Application application;
Router router;
};
#endif // __APPLICATION_ADAPTER_HTTP_H__

17
include/http/request.h

@ -30,7 +30,18 @@
#define N_HTTP_METHOD 8
char * http_method[N_HTTP_METHOD];
extern char * http_method[N_HTTP_METHOD];
typedef enum e_HttpMethod {
HTTP_OPTIONS = 0,
HTTP_GET,
HTTP_HEAD,
HTTP_POST,
HTTP_PUT,
HTTP_DELETE,
HTTP_TRACE,
HTTP_CONNECT
} HttpMethod;
CLASS(HttpRequest) {
EXTENDS(HttpMessage);
@ -39,12 +50,14 @@ CLASS(HttpRequest) {
char * uri;
char * path;
HttpMethod method_id;
Hash get;
Hash post;
Hash cookies;
};
int httpRequestHasValidMethod(HttpRequest);
HttpMethod httpRequestGetMethodId(HttpRequest);
#endif // __HTTP_REQUEST_H__

59
include/router.h

@ -0,0 +1,59 @@
/**
* \file
* A generic REST router that is able to map a URL to a specific
* function. It uses dlsym to get the address of the function to
* be called.
* The functions need to have a common interface for sure....This will
* work out while I am working on this.
* After a function is found it's address will be stored in a hash
* so that further lookups might be faster.
* By it's nature I think this is part of the HttpApplicationAdapter.
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ROUTER_H__
#define __ROUTER_H__
#include <dlfcn.h>
#include "class.h"
#include "hash.h"
#include "session.h"
#include "http/request.h"
#include "http/response.h"
#include "application/application.h"
typedef char * (* fptr_routable)(Application, Session, Hash);
CLASS(Router) {
Hash functions;
Application application;
void * handle;
char * prefix;
size_t nprefix;
};
HttpResponse routerRoute(Router, HttpRequest, Session);
#endif // __ROUTER_H__
// vim: set ts=4 sw=4:

11
src/Makefile.am

@ -27,13 +27,14 @@ TRHTTPSERVER = http/libhttp.la \
TR = ./application/.libs/libapplication.a \
./user/.libs/libuser.a \
./storage/.libs/libstorage.a \
./auth/.libs/libauth.a \
./storage/.libs/libstorage.a \
./session/.libs/libsession.a \
./config/.libs/libconfig.a
./config/.libs/libconfig.a \
./router/.libs/librouter.a
TRLIBS = -ltrutils -ltrhttpserver -ltrbase
USEDLIBS = -lrt -lssl -lldap -lgdbm -luuid
USEDLIBS = -lrt -lssl -lldap -lgdbm -luuid -ldl
AM_CFLAGS += -I../include/
@ -55,7 +56,9 @@ libtrhttpserver_la_LIBADD = $(TRHTTPSERVER)
taskrambler_SOURCES = taskrambler.c $(IFACE) $(UTILS)
taskrambler_CFLAGS = $(AM_CFLAGS)
taskrambler_LDADD = $(TRLIBS) $(TR) $(USEDLIBS)
taskrambler_LDFLAGS = -Wl,--export-dynamic \
-Wl,--whole-archive,./application/.libs/libapplication.a,--no-whole-archive
SUBDIRS = asset auth cbuf class hash queue http \
logger server session socket stream tree application \
storage user config
storage user config router

9
src/application/Makefile.am

@ -11,10 +11,17 @@ APPLICATION = application.c \
session_cleanup.c
ADAPTERHTTP = adapter/http/http.c \
adapter/http/update.c
CONTROLLER = controller/authenticate/create.c \
controller/authenticate/delete.c \
controller/currentuser/read.c \
controller/randval/read.c \
controller/sessinfo/read.c \
controller/user/create.c \
controller/version/read.c
AM_CFLAGS += -I../../include/
noinst_LTLIBRARIES = libapplication.la
libapplication_la_SOURCES = $(APPLICATION) $(ADAPTERHTTP)
libapplication_la_SOURCES = $(APPLICATION) $(ADAPTERHTTP) $(CONTROLLER)
libapplication_la_CFLAGS = $(AM_CFLAGS)

2
src/application/adapter/http/http.c

@ -25,6 +25,7 @@
#include <stdarg.h>
#include "class.h"
#include "router.h"
#include "application/application.h"
#include "application/adapter/http.h"
@ -38,6 +39,7 @@ applicationAdapterHttpCtor(void * _this, va_list * params)
ApplicationAdapterHttp this = _this;
this->application = va_arg(*params, Application);
this->router = va_arg(*params, Router);
return 0;
}

245
src/application/adapter/http/update.c

@ -22,32 +22,19 @@
#define _GNU_SOURCE
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "class.h"
#include "application/application.h"
#include "application/adapter/http.h"
#include "hash.h"
#include "http/worker.h"
#include "http/header.h"
#include "http/response.h"
#include "auth/credential.h"
#include "user.h"
#include "utils/memory.h"
#include "http/message.h"
#include "router.h"
#define NO_SESSION_SID NULL
#define RANDVAL_JSON "{\"ctime\":%ld,\"vnext\":%ld,\"value\":\"%02d\"}"
#define SESSION_JSON "{\"id\":\"%s\",\"timeout\":%d,\"timeleft\":%ld}"
#define USER_JSON \
"{\"email\":\"%s\",\"firstname\":\"%s\",\"surname\":\"%s\"}"
#define VERSION_JSON "{\"version\":\"%s\"}"
static
inline
char *
@ -62,170 +49,6 @@ getSessionId(Hash cookies)
return NO_SESSION_SID;
}
HttpMessage
responseVersion(const char * version)
{
char buffer[200];
size_t nbuf;
nbuf = sprintf(buffer, VERSION_JSON, version? version : "");
return (HttpMessage)httpResponseJson(buffer, nbuf);
}
HttpMessage
responseRandval(struct randval * val)
{
char buffer[200];
size_t nbuf;
time_t remaining;
remaining = 10 - (time(NULL) - val->timestamp);
nbuf = sprintf(
buffer,
RANDVAL_JSON,
val->timestamp,
remaining,
val->value);
return (HttpMessage)httpResponseJson(buffer, nbuf);
}
HttpMessage
responseSession(Session session)
{
char buffer[200];
size_t nbuf;
nbuf = sprintf(buffer, SESSION_JSON,
(NULL != session)? session->id : "",
(NULL != session)? SESSION_LIVETIME : 0,
(NULL != session)? session->livetime - time(NULL) : 0);
return (HttpMessage)httpResponseJson(buffer, nbuf);
}
HttpMessage
responseUser(User user)
{
char buffer[200];
size_t nbuf;
nbuf = sprintf(buffer, USER_JSON,
(NULL != user)? user->email : "",
(NULL != user)? user->firstname : "",
(NULL != user)? user->surname : "");
return (HttpMessage)httpResponseJson(buffer, nbuf);
}
static
void
loginAdapter(Application application, HttpWorker worker, Session session)
{
HashValue username;
HashValue password;
Credential credential;
username = hashGet(
worker->current_request->post,
CSTRA("username"));
password = hashGet(
worker->current_request->post,
CSTRA("password"));
if (NULL == username) {
username = hashGet(
worker->current_request->post,
CSTRA("email"));
}
if (NULL == username || NULL == password) {
worker->current_response = (HttpMessage)httpResponse403();
return;
}
credential = new(Credential,
CRED_PASSWORD,
(char *)(username->value), username->nvalue,
(char *)(password->value), password->nvalue);
if (! applicationLogin(application, credential, session)) {
worker->current_response = (HttpMessage)httpResponse403();
} else {
worker->current_response = responseUser(session->user);
}
delete(credential);
}
static
void
signupAdapter(Application application, HttpWorker worker, Session session)
{
HashValue email;
HashValue password;
HashValue pwrepeat;
HashValue firstname;
HashValue surname;
Credential credential;
User user;
email = hashGet(
worker->current_request->post,
CSTRA("email"));
password = hashGet(
worker->current_request->post,
CSTRA("password"));
pwrepeat = hashGet(
worker->current_request->post,
CSTRA("pwrepeat"));
firstname = hashGet(
worker->current_request->post,
CSTRA("firstname"));
surname = hashGet(
worker->current_request->post,
CSTRA("surname"));
if (
NULL == email ||
NULL == password ||
NULL == pwrepeat ||
NULL == firstname ||
NULL == surname) {
// maybe this is not a 500...have to check repsonse codes.
worker->current_response = (HttpMessage)httpResponse500();
return;
}
if (password->nvalue != pwrepeat->nvalue ||
0 != memcmp(password->value, pwrepeat->value, password->nvalue)) {
// maybe this is not a 500...have to check repsonse codes.
worker->current_response = (HttpMessage)httpResponse500();
return;
}
credential = new(Credential,
CRED_PASSWORD,
(char *)(email->value), email->nvalue,
(char *)(password->value), password->nvalue);
user = new(User,
(char *)(email->value), email->nvalue,
(char *)(firstname->value), firstname->nvalue,
(char *)(surname->value), surname->nvalue);
if (! applicationSignup(application, credential, user, session)) {
worker->current_response = (HttpMessage)httpResponse500();
} else {
loginAdapter(application, worker, session);
}
delete(credential);
delete(user);
}
void
applicationAdapterHttpUpdate(void * _this, void * subject)
{
@ -253,66 +76,10 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
worker->additional_headers,
new(HttpHeader, CSTRA("Set-Cookie"), buf, nbuf));
if (0 == strcmp("POST", worker->current_request->method)) {
if (0 == strcmp("/login/", worker->current_request->path)) {
loginAdapter(this->application, worker, session);
return;
}
if (0 == strcmp("/signup/", worker->current_request->path)) {
signupAdapter(this->application, worker, session);
return;
}
}
if (0 == strcmp("GET", worker->current_request->method)) {
if (0 == strcmp("/version/", worker->current_request->path)) {
worker->current_response =
responseVersion(this->application->version);
return;
}
if (0 == strcmp("/user/get/", worker->current_request->path)) {
worker->current_response = responseUser(session->user);
return;
}
if (0 == strcmp("/logout/", worker->current_request->path)) {
applicationLogout(this->application, session);
worker->current_response = responseUser(session->user);
return;
}
if (0 == strcmp("/sessinfo/", worker->current_request->path)) {
worker->current_response = responseSession(session);
return;
}
if (0 == strcmp("/randval/", worker->current_request->path)) {
if (NULL != session->user) {
worker->current_response =
responseRandval(this->application->val);
return;
} else {
worker->current_response = (HttpMessage)httpResponse403();
}
}
}
// if (0 < session->livetime - now) {
// nbuf = sprintf(buf, SESSION_JSON,
// session->id,
// SESSION_LIVETIME,
// session->livetime - now);
// queuePut(
// worker->additional_headers,
// new(HttpHeader, CSTRA("X-TaskramblerSession"), buf, nbuf));
// } else {
// nbuf = sprintf(buf, "sid=%s;Path=/;Max-Age=-3600", session->id);
// }
worker->current_response = (HttpMessage)routerRoute(
this->router,
worker->current_request,
session);
}
// vim: set ts=4 sw=4:

75
src/application/controller/authenticate/create.c

@ -0,0 +1,75 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include "class.h"
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "auth/credential.h"
#include "user.h"
#include "utils/memory.h"
char * controllerCurrentuserRead(Application, Session, Hash);
char *
controllerAuthenticateCreate(
Application application,
Session session,
Hash args)
{
HashValue username;
HashValue password;
Credential credential;
char * response_data;
username = hashGet(args, CSTRA("username"));
password = hashGet(args, CSTRA("password"));
if (NULL == username) {
username = hashGet(args, CSTRA("email"));
}
if (NULL == username || NULL == password) {
return NULL;
}
credential = new(Credential,
CRED_PASSWORD,
(char *)(username->value), username->nvalue,
(char *)(password->value), password->nvalue);
if (! applicationLogin(application, credential, session)) {
response_data = NULL;
} else {
response_data = controllerCurrentuserRead(application, session, NULL);
}
delete(credential);
return response_data;
}
// vim: set ts=4 sw=4:

44
src/application/controller/authenticate/delete.c

@ -0,0 +1,44 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include "class.h"
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "utils/memory.h"
char * controllerCurrentuserRead(Application, Session, Hash);
char *
controllerAuthenticateDelete(
Application application,
Session session,
Hash args)
{
applicationLogout(application, session);
return controllerCurrentuserRead(application, session, NULL);
}
// vim: set ts=4 sw=4:

58
src/application/controller/currentuser/read.c

@ -0,0 +1,58 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include "class.h"
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "utils/memory.h"
#define USER_JSON \
"{\"email\":\"%s\",\"firstname\":\"%s\",\"surname\":\"%s\"}"
char *
controllerCurrentuserRead(Application app, Session sess, Hash args)
{
char * buffer;
size_t nbuffer;
nbuffer = snprintf(NULL, 0, USER_JSON,
(NULL != sess->user)? sess->user->email : "",
(NULL != sess->user)? sess->user->firstname : "",
(NULL != sess->user)? sess->user->surname : "");
buffer = memMalloc(nbuffer);
nbuffer = sprintf(buffer, USER_JSON,
(NULL != sess->user)? sess->user->email : "",
(NULL != sess->user)? sess->user->firstname : "",
(NULL != sess->user)? sess->user->surname : "");
return buffer;
}
// vim: set ts=4 sw=4:

63
src/application/controller/randval/read.c

@ -0,0 +1,63 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "utils/memory.h"
#define RANDVAL_JSON "{\"ctime\":%ld,\"vnext\":%ld,\"value\":\"%02d\"}"
char *
controllerRandvalRead(Application app, Session sess, Hash args)
{
char * buffer;
size_t nbuffer;
time_t remaining;
remaining = 10 - (time(NULL) - app->val->timestamp);
nbuffer = snprintf(
NULL,
0,
RANDVAL_JSON,
app->val->timestamp,
remaining,
app->val->value);
buffer = memMalloc(nbuffer);
sprintf(
buffer,
RANDVAL_JSON,
app->val->timestamp,
remaining,
app->val->value);
return buffer;
}
// vim: set ts=4 sw=4:

59
src/application/controller/sessinfo/read.c

@ -0,0 +1,59 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "utils/memory.h"
#define SESSION_JSON "{\"id\":\"%s\",\"timeout\":%d,\"timeleft\":%ld}"
char *
controllerSessinfoRead(
Application application,
Session session,
Hash args)
{
char * buffer;
size_t nbuffer;
nbuffer = snprintf(NULL, 0, SESSION_JSON,
(NULL != session)? session->id : "",
(NULL != session)? SESSION_LIVETIME : 0,
(NULL != session)? session->livetime - time(NULL) : 0);
buffer = memMalloc(nbuffer);
sprintf(buffer, SESSION_JSON,
(NULL != session)? session->id : "",
(NULL != session)? SESSION_LIVETIME : 0,
(NULL != session)? session->livetime - time(NULL) : 0);
return buffer;
}
// vim: set ts=4 sw=4:

98
src/application/controller/user/create.c

@ -0,0 +1,98 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include "application/application.h"
#include "session.h"
#include "hash.h"
#include "auth/credential.h"
#include "user.h"
#include "utils/memory.h"
char * controllerCurrentuserRead(Application, Session, Hash);
char *
controllerUserCreate(
Application application,
Session session,
Hash args)
{
HashValue email;
HashValue password;
HashValue pwrepeat;
HashValue firstname;
HashValue surname;
Credential credential;
User user;
char * response_data;
email = hashGet(args, CSTRA("email"));
password = hashGet(args, CSTRA("password"));
pwrepeat = hashGet(args, CSTRA("pwrepeat"));
firstname = hashGet(args, CSTRA("firstname"));
surname = hashGet(args, CSTRA("surname"));
if (
NULL == email ||
NULL == password ||
NULL == pwrepeat ||
NULL == firstname ||
NULL == surname)
{
return NULL;
}
if (
password->nvalue != pwrepeat->nvalue ||
0 != memcmp(password->value, pwrepeat->value, password->nvalue))
{
return NULL;
}
credential = new(Credential,
CRED_PASSWORD,
(char *)(email->value), email->nvalue,
(char *)(password->value), password->nvalue);
user = new(User,
(char *)(email->value), email->nvalue,
(char *)(firstname->value), firstname->nvalue,
(char *)(surname->value), surname->nvalue);
if (! applicationSignup(application, credential, user, session)) {
response_data = NULL;
} else {
applicationLogin(application, credential, session);
response_data = controllerCurrentuserRead(application, session, NULL);
}
delete(credential);
delete(user);
return response_data;
}
// vim: set ts=4 sw=4:

49
src/application/controller/version/read.c

@ -0,0 +1,49 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include "application/application.h"
#include "hash.h"
#include "session.h"
#include "utils/memory.h"
#define VERSION_JSON "{\"version\":\"%s\"}"
char *
controllerVersionRead(Application app, Session sess, Hash args)
{
char * buffer;
size_t nbuffer;
nbuffer = snprintf(NULL, 0, VERSION_JSON, app->version? app->version : "");
buffer = memMalloc(nbuffer);
sprintf(buffer, VERSION_JSON, app->version? app->version : "");
return buffer;
}
// vim: set ts=4 sw=4:

2
src/http/Makefile.am

@ -8,7 +8,7 @@ MSG = message.c \
message/get_version.c \
message/has_valid_version.c
REQ = request.c \
request/has_valid_method.c
request/get_method_id.c
RESP = response.c \
response/304.c \
response/404.c \

12
src/http/request.c

@ -56,6 +56,18 @@ httpRequestCtor(void * _this, va_list * params)
this->uri[ulen] = 0;
memcpy(this->uri, uri, ulen);
this->method_id = httpRequestGetMethodId(this);
if (-1 == this->method_id) {
MEM_FREE(this->uri);
MEM_FREE(this->method);
MEM_FREE(this->path); /** \todo looks like path is not used at all */
PARENTCALL(_this, Class, dtor);
return -1;
}
this->get = new(Hash);
this->post = new(Hash);
this->cookies = new(Hash);

15
src/http/request/has_valid_method.c → src/http/request/get_method_id.c

@ -32,22 +32,27 @@ char * http_method[N_HTTP_METHOD] = {
"PUT",
"DELETE",
"TRACE",
"CONNECT"};
"CONNECT"
};
int
httpRequestHasValidMethod(HttpRequest this)
HttpMethod
httpRequestGetMethodId(HttpRequest this)
{
int i;
if (NULL == this->method)
return 0;
return -1;
for (i=0; i<N_HTTP_METHOD; i++) {
if (0 == strcmp(http_method[i], this->method))
break;
}
return (i != N_HTTP_METHOD);
if (i >= N_HTTP_METHOD) {
return -1;
}
return (i);
}
// vim: set ts=4 sw=4:

11
src/router/Makefile.am

@ -0,0 +1,11 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
ROUTER = router.c route.c
AM_CFLAGS += -I../../include/
noinst_LTLIBRARIES = librouter.la
librouter_la_SOURCES = $(ROUTER)
librouter_la_CFLAGS = $(AM_CFLAGS)

181
src/router/route.c

@ -0,0 +1,181 @@
/**
* \file
* This is the generic application router....
* Here RBAC can take place as every resource is always requested
* via an HTTP request.
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// for strchr and others.
#include <string.h>
// for size_t
#include <sys/types.h>
// for dlopen, dlsym
#include <dlfcn.h>
// for toupper
#include <ctype.h>
#include "router.h"
#include "hash.h"
#include "session.h"
#include "http/request.h"
#include "http/response.h"
#include "application/application.h"
#include "utils/memory.h"
#include "commons.h"
#define COMMAND_LEN 128
HttpResponse
routerRoute(
Router this,
HttpRequest request,
Session sess)
{
char functionName[COMMAND_LEN + this->nprefix * 10];
Hash args = NULL;
fptr_routable function;
char * tmp;
char * command;
size_t ncommand;
char * response_data;
HttpResponse response;
if ('/' != request->uri[0]) {
/*
* we only support absolute paths within our
* application
*/
return NULL;
}
command = &(request->uri[1]);
command[0] = toupper(command[0]);
/*
* find end of command
*/
tmp = strchr(command, '/');
if (NULL == tmp) {
ncommand = strlen(command);
} else {
ncommand = tmp - command;
}
memcpy(functionName, this->prefix, this->nprefix);
memcpy(&(functionName[this->nprefix]),
command, MIN(COMMAND_LEN, ncommand));
/**
* \todo
* now get all arguments if we have some
*/
/*
* following the crud pattern we map the first part
* of the uri and the request method to according
* function names.
*/
switch (request->method_id) {
case HTTP_GET:
args = new(Hash);
strcpy(&(functionName[this->nprefix + ncommand]), "Read");
break;
case HTTP_POST:
args = request->post;
strcpy(&(functionName[this->nprefix + ncommand]), "Create");
break;
case HTTP_PUT:
strcpy(&(functionName[this->nprefix + ncommand]), "Update");
break;
case HTTP_DELETE:
strcpy(&(functionName[this->nprefix + ncommand]), "Delete");
break;
default:
/* other methods are not subject of REST */
return NULL;
}
/*
* \todo for the moment I don't cache the found symbol...
* I don't even check if there was an error...the only thing
* I do is checking a NULL symbol and in that case don't
* handle the request here.
*/
dlerror();
function = dlsym(this->handle, functionName);
/**
* \todo somewhere here or above access control have to take place
*/
if (NULL == function) {
/**
* nothing there to handle the request ... so leave it to the
* caller...
*/
char * error;
if (NULL != (error = dlerror())) {
/**
* \todo add logging...maybe.
*/
}
return NULL;
}
/*
* function has to allocate the memory for reponse_date by using
* memMalloc.
*/
response_data = function(this->application, sess, args);
switch (request->method_id) {
case HTTP_GET:
delete(args);
break;
case HTTP_POST:
case HTTP_PUT:
case HTTP_DELETE:
default:
/* other methods are not subject of REST */
break;
}
response = httpResponseJson(response_data, strlen(response_data));
MEM_FREE(response_data);
return response;
}
// vim: set ts=4 sw=4:

66
src/router/router.c

@ -0,0 +1,66 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2013 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
// for dlopen, dlsym
#include <dlfcn.h>
#include "class.h"
#include "router.h"
#include "hash.h"
#include "application/application.h"
#define PREFIX "controller"
static
int
routerCtor(void * _this, va_list * params)
{
Router this = _this;
this->application = va_arg(*params, Application);
this->functions = new(Hash);
this->handle = dlopen(NULL, RTLD_LAZY);
this->prefix = PREFIX;
this->nprefix = sizeof(PREFIX) - 1;
if (NULL == this->handle) {
return -1;
}
return 0;
}
static
void
routerDtor(void * _this) {
Router this = _this;
delete(this->functions);
dlclose(this->handle);
}
INIT_IFACE(Class, routerCtor, routerDtor, NULL);
CREATE_CLASS(Router, NULL, IFACE(Class));
// vim: set ts=4 sw=4:

5
src/taskrambler.c

@ -165,6 +165,7 @@ main()
AuthLdap authLdap;
AuthStorage authStorage;
Application application;
Router router;
ApplicationAdapterHttp adapterHttp;
HttpWorker worker;
Server server;
@ -210,7 +211,8 @@ main()
authLdap,
authStorage);
adapterHttp = new(ApplicationAdapterHttp, application);
router = new(Router, application);
adapterHttp = new(ApplicationAdapterHttp, application, router);
worker = new(HttpWorker, "taskrambler");
subjectAttach(worker, adapterHttp);
@ -267,6 +269,7 @@ main()
delete(server);
delete(worker);
delete(adapterHttp);
delete(router);
delete(application);
delete(authStorage);
delete(passwords);

Loading…
Cancel
Save