commit 48b10a0c6ec401a0bbfbe2b539ca7355a5f159b4
parent f41df3ff9e7df8ba154e882f02acdcfa881f35c7
Author: Yersa Nordman <yersa@finwo.nl>
Date: Fri, 4 Aug 2023 21:35:15 +0200
Updated lib to use buffers and buffer version of http-parser
Diffstat:
4 files changed, 110 insertions(+), 104 deletions(-)
diff --git a/example.c b/example.c
@@ -3,43 +3,46 @@
#include <string.h>
#include "finwo/http-parser.h"
+#include "tidwall/buf.h"
#include "http-server.h"
-void onServing(const char **addrs, int naddrs, void *udata) {
- for (int i = 0; i < naddrs; i++) {
- printf("Serving at %s\n", addrs[i]);
- }
+void onServing(char *addr, uint16_t port, void *udata) {
+ printf("Serving at %s:%d\n", addr, port);
}
-void route_get_hello(struct hs_udata *reqdata) {
+void route_get_hello(struct http_server_reqdata *reqdata) {
http_parser_header_set(reqdata->reqres->response, "Content-Type", "text/plain");
- reqdata->reqres->response->body = strdup("Hello World!!");
- reqdata->reqres->response->bodysize = strlen(reqdata->reqres->response->body);
+ reqdata->reqres->response->body = calloc(1, sizeof(struct buf));
+ reqdata->reqres->response->body->data = strdup("Hello World\n");
+ reqdata->reqres->response->body->len = strlen(reqdata->reqres->response->body->data);
http_server_response_send(reqdata, true);
return;
}
-void route_404(struct hs_udata *reqdata) {
+void route_404(struct http_server_reqdata *reqdata) {
http_parser_header_set(reqdata->reqres->response, "Content-Type", "text/plain");
- reqdata->reqres->response->status = 404;
- reqdata->reqres->response->body = strdup("Not found");
- reqdata->reqres->response->bodysize = strlen(reqdata->reqres->response->body);
+ reqdata->reqres->response->status = 404;
+ reqdata->reqres->response->body = calloc(1, sizeof(struct buf));
+ reqdata->reqres->response->body->data = strdup("not found\n");
+ reqdata->reqres->response->body->len = strlen(reqdata->reqres->response->body->data);
http_server_response_send(reqdata, true);
return;
}
int main() {
- const char *addrs[] = { "tcp://localhost:4000" };
struct http_server_events evs = {
- .tick = NULL,
.serving = onServing,
- .error = NULL,
.close = NULL,
.notFound = route_404
};
http_server_route("GET", "/hello", route_get_hello);
- http_server_main(addrs, sizeof(addrs) / sizeof(void*), &evs, NULL);
+
+ http_server_main(&(const struct http_server_opts){
+ .evs = &evs,
+ .addr = "0.0.0.0",
+ .port = 8080,
+ });
}
diff --git a/package.ini b/package.ini
@@ -1,11 +1,11 @@
[dependencies]
+finwo/fnet=https://github.com/finwo/c-fnet/archive/refs/tags/edge.tar.gz
finwo/http-parser=https://github.com/finwo/http-parser/archive/refs/tags/edge.tar.gz
-tidwall/evio=https://raw.githubusercontent.com/finwo/dep-repository/main/tidwall/evio/package.ini
-
-[package]
-deps=lib
-name=finwo/http-parser
[export]
config.mk=config.mk
include/finwo/http-server.h=src/http-server.h
+
+[package]
+deps=lib
+name=finwo/http-parser
diff --git a/src/http-server.c b/src/http-server.c
@@ -3,53 +3,40 @@
#include <string.h>
#include "finwo/http-parser.h"
-#include "tidwall/evio.h"
+#include "finwo/fnet.h"
#include "http-server.h"
-struct evio_udata {
- struct http_server_events *hsevs;
- void *udata;
+struct fnet_udata {
+ struct http_server_events *evs;
+ char *addr;
+ uint16_t port;
+ void *cudata;
};
struct hs_route {
void *next;
const char *method;
const char *path;
- void (*fn)(struct hs_udata*);
+ void (*fn)(struct http_server_reqdata*);
};
struct hs_route *registered_routes = NULL;
-void _hs_onServing(const char **addrs, int naddrs, void *udata) {
- struct evio_udata *info = udata;
- if (info->hsevs->serving) {
- info->hsevs->serving(addrs, naddrs, info->udata);
- }
-}
+void _hs_onServing(struct fnet_ev *ev) {
+ struct fnet_udata *ludata = ev->udata;
-void _hs_onError(const char *message, bool fatal, void *udata) {
- struct evio_udata *info = udata;
- if (info->hsevs->error) {
- info->hsevs->error(message, fatal, info->udata);
+ if (ludata->evs && ludata->evs->serving) {
+ ludata->evs->serving(ludata->addr, ludata->port, ludata->cudata);
}
}
-int64_t _hs_onTick(void *udata) {
- struct evio_udata *info = udata;
- if (info->hsevs->tick) {
- return info->hsevs->tick(info->udata);
- }
- return 1e9; // 1 second
-}
-
static void _hs_onRequest(struct http_parser_event *ev) {
- struct hs_udata *hsdata = ev->udata;
- struct evio_udata *info = hsdata->info;
- struct hs_route *route = registered_routes;
- struct hs_route *selected_route = NULL;
+ struct http_server_reqdata *reqdata = ev->udata;
+ struct hs_route *route = registered_routes;
+ struct hs_route *selected_route = NULL;
- // Method/path matching, should be more intricate later
+ // Method/path matching, should be more intricate later (like /posts/:postId/comments)
while(route) {
if (
(!strcmp(ev->request->method, route->method)) &&
@@ -60,60 +47,65 @@ static void _hs_onRequest(struct http_parser_event *ev) {
route = route->next;
}
- // No 404 handler (yet)
if (!selected_route) {
- if (info->hsevs->notFound) {
- info->hsevs->notFound(hsdata);
+ if (reqdata->evs && reqdata->evs->notFound) {
+ reqdata->evs->notFound(reqdata);
return;
} else {
- evio_conn_close(hsdata->connection);
+ fnet_close(reqdata->connection);
return;
}
}
// Call the route handler
- selected_route->fn(hsdata);
+ selected_route->fn(reqdata);
}
-
-void _hs_onOpen(struct evio_conn *conn, void *udata) {
- struct evio_udata *info = udata;
- struct hs_udata *hsdata = malloc(sizeof(struct hs_udata));
- hsdata->connection = conn;
- hsdata->info = info;
- hsdata->reqres = http_parser_pair_init(hsdata);
- hsdata->reqres->onRequest = _hs_onRequest;
- evio_conn_set_udata(conn, hsdata);
+void _hs_onData(struct fnet_ev *ev) {
+ struct http_server_reqdata *reqdata = ev->udata;
+ http_parser_pair_request_data(reqdata->reqres, ev->buffer);
}
-void _hs_onClose(struct evio_conn *conn, void *udata) {
- struct evio_udata *info = udata;
- struct hs_udata *hsdata = evio_conn_udata(conn);
+void _hs_onClose(struct fnet_ev *ev) {
+ struct http_server_reqdata *reqdata = ev->udata;
- if (info->hsevs->close) {
- info->hsevs->close(hsdata, info->udata);
+ if (reqdata->evs && reqdata->evs->close) {
+ reqdata->evs->close(reqdata);
}
- http_parser_pair_free(hsdata->reqres);
- free(hsdata);
+ http_parser_pair_free(reqdata->reqres);
+ free(reqdata);
}
-void _hs_onData(struct evio_conn *conn, const void *data, size_t len, void *udata) {
- struct hs_udata *hsdata = evio_conn_udata(conn);
- http_parser_pair_request_data(hsdata->reqres, data, len);
+void _hs_onConnect(struct fnet_ev *ev) {
+ struct fnet_t *conn = ev->connection;
+ struct fnet_udata *ludata = ev->udata;
+
+ // Setup new request/response pair
+ struct http_server_reqdata *reqdata = malloc(sizeof(struct http_server_reqdata));
+ reqdata->connection = conn;
+ reqdata->reqres = http_parser_pair_init(reqdata);
+ reqdata->reqres->onRequest = _hs_onRequest;
+ reqdata->evs = ludata->evs;
+ ev->connection->udata = reqdata;
+
+ // Setup data flowing from connection into reqres
+ ev->connection->onData = _hs_onData;
+ ev->connection->onClose = _hs_onClose;
}
-void http_server_response_send(struct hs_udata *hsdata, bool close) {
- char *response_buffer = http_parser_sprint_response(hsdata->reqres->response);
- evio_conn_write(hsdata->connection, response_buffer, strlen(response_buffer));
+void http_server_response_send(struct http_server_reqdata *reqdata, bool close) {
+ struct buf *response_buffer = http_parser_sprint_response(reqdata->reqres->response);
+ fnet_write(reqdata->connection, response_buffer);
+ buf_clear(response_buffer);
free(response_buffer);
if (close) {
- evio_conn_close(hsdata->connection);
+ fnet_close(reqdata->connection);
}
}
-void http_server_route(const char *method, const char *path, void (*fn)(struct hs_udata*)) {
- struct hs_route *route = calloc(1, sizeof(struct hs_route));
+void http_server_route(const char *method, const char *path, void (*fn)(struct http_server_reqdata*)) {
+ struct hs_route *route = malloc(sizeof(struct hs_route));
route->next = registered_routes;
route->method = method;
route->path = path;
@@ -121,20 +113,25 @@ void http_server_route(const char *method, const char *path, void (*fn)(struct h
registered_routes = route;
}
-void http_server_main(char **addrs, int naddrs, struct http_server_events *hsevs, void *udata) {
- struct evio_udata *info = calloc(1, sizeof(struct evio_udata));
- info->hsevs = hsevs;
- info->udata = udata;
-
- struct evio_events evs = {
- .serving = _hs_onServing,
- .error = _hs_onError,
- .tick = _hs_onTick,
- .opened = _hs_onOpen,
- .closed = _hs_onClose,
- .data = _hs_onData,
- };
+void http_server_main(const struct http_server_opts *opts) {
+
+ struct fnet_udata *ludata = calloc(1, sizeof(struct fnet_udata));
+ ludata->addr = opts->addr,
+ ludata->port = opts->port,
+ ludata->cudata = opts->udata,
+ ludata->evs = opts->evs,
+
+ fnet_listen(opts->addr, opts->port, &((struct fnet_options_t){
+ .proto = FNET_PROTO_TCP,
+ .flags = 0,
+ .onListen = _hs_onServing,
+ .onConnect = _hs_onConnect,
+ .onData = NULL,
+ .onTick = NULL,
+ .onClose = NULL,
+ .udata = ludata,
+ }));
// This is a forever function
- evio_main(addrs, naddrs, evs, info);
+ fnet_main();
}
diff --git a/src/http-server.h b/src/http-server.h
@@ -4,22 +4,28 @@
#include <stdbool.h>
#include <stdint.h>
-struct hs_udata {
- struct evio_conn *connection; // From the underlaying connection library
- struct http_parser_pair *reqres; // The request/response pair
- void *info; // See C file for definition, type not exported
+struct http_server_reqdata {
+ struct fnet_t *connection; // From the underlaying connection library
+ struct http_parser_pair *reqres; // The request/response pair
+ struct http_server_events *evs;
+ void *udata;
+};
+
+struct http_server_opts {
+ struct http_server_events *evs;
+ char *addr;
+ uint16_t port;
+ void *udata;
};
struct http_server_events {
- int64_t (*tick)(void *udata);
- void (*serving)(const char **addrs, int naddrs, void *udata);
- void (*error)(const char *message, bool fatal, void *udata);
- void (*close)(struct hs_udata *conn, void *udata);
- void (*notFound)(struct hs_udata*);
+ void (*serving)(char *addrs, uint16_t port, void *udata);
+ void (*close)(struct http_server_reqdata *reqdata);
+ void (*notFound)(struct http_server_reqdata *reqdata);
};
-void http_server_response_send(struct hs_udata *hsdata, bool close);
-void http_server_route(const char *method, const char *path, void (*fn)(struct hs_udata*));
-void http_server_main(char **addrs, int naddrs, struct http_server_events *hsevs, void *udata);
+void http_server_main(const struct http_server_opts *opts);
+void http_server_response_send(struct http_server_reqdata *reqdata, bool close);
+void http_server_route(const char *method, const char *path, void (*fn)(struct http_server_reqdata*));
#endif // __FINWO_HTTP_SERVER_H__