aboutsummaryrefslogtreecommitdiff
path: root/examples/hello
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-08-06 16:43:57 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-08-09 00:32:13 +0200
commit4ee88984fcca86c5b0c9c4bbb7e9148c7d2fe9db (patch)
treeaa4ab670afd116e419a9661bd266e7c3d0b56dc4 /examples/hello
parent83b8b8c2b3622ff7dfc46adf25b6723f1abfb0b5 (diff)
Add hello world example
Diffstat (limited to 'examples/hello')
-rw-r--r--examples/hello/CMakeLists.txt4
-rw-r--r--examples/hello/Makefile26
-rw-r--r--examples/hello/README.md17
-rw-r--r--examples/hello/main.c101
4 files changed, 148 insertions, 0 deletions
diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt
new file mode 100644
index 0000000..c22ab33
--- /dev/null
+++ b/examples/hello/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.13)
+project(hello C)
+add_executable(hello main.c)
+target_link_libraries(${PROJECT_NAME} PRIVATE slweb dynstr)
diff --git a/examples/hello/Makefile b/examples/hello/Makefile
new file mode 100644
index 0000000..217bccb
--- /dev/null
+++ b/examples/hello/Makefile
@@ -0,0 +1,26 @@
+.POSIX:
+
+PROJECT = hello
+DEPS = \
+ main.o
+SLWEB = ../../libslweb.a
+DYNSTR = ../../dynstr/libdynstr.a
+CFLAGS = -I ../../include -I ../../dynstr/include
+SLWEB_FLAGS = -L ../../ -l slweb
+DYNSTR_FLAGS = -L ../../dynstr -l dynstr
+
+all: $(PROJECT)
+
+clean:
+ rm -f $(DEPS)
+
+FORCE:
+
+$(PROJECT): $(DEPS) $(SLWEB) $(DYNSTR)
+ $(CC) $(LDFLAGS) $(DEPS) $(SLWEB_FLAGS) $(DYNSTR_FLAGS) -o $@
+
+$(SLWEB): FORCE
+ +cd ../../ && $(MAKE)
+
+$(DYNSTR): FORCE
+ +cd ../../dynstr && $(MAKE)
diff --git a/examples/hello/README.md b/examples/hello/README.md
new file mode 100644
index 0000000..7c7cf74
--- /dev/null
+++ b/examples/hello/README.md
@@ -0,0 +1,17 @@
+# "Hello world" example
+
+This example shows a minimal setup for an application using `slweb`. When
+executed, it starts a HTTP/1.1 server on port `8080` and returns an example
+website reading "Hello from slweb!" when either `/` or `/index.html` are
+accessed by clients.
+
+## How to build
+
+If using `make(1)`, just run `make` from this directory.
+
+If using CMake, examples are built by default when configuring the project
+from [the top-level `CMakeLists.txt`](../../CMakeLists.txt).
+
+## How to run
+
+Run the executable without any command line arguments.
diff --git a/examples/hello/main.c b/examples/hello/main.c
new file mode 100644
index 0000000..f44ff0c
--- /dev/null
+++ b/examples/hello/main.c
@@ -0,0 +1,101 @@
+#include <dynstr.h>
+#include <slweb/handler.h>
+#include <slweb/html.h>
+#include <slweb/http.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int hello(const struct http_payload *const pl,
+ struct http_response *const r, void *const user)
+{
+ int ret = -1;
+ struct html_node *html = html_node_alloc("html"), *body, *p;
+ struct dynstr d;
+
+ dynstr_init(&d);
+
+ if (!html)
+ {
+ fprintf(stderr, "%s: html_node_alloc failed\n", __func__);
+ goto end;
+ }
+ else if (!(body = html_node_add_child(html, "body")))
+ {
+ fprintf(stderr, "%s: html_node_add_child body failed\n", __func__);
+ goto end;
+ }
+ else if (!(p = html_node_add_child(html, "p")))
+ {
+ fprintf(stderr, "%s: html_node_add_child p failed\n", __func__);
+ goto end;
+ }
+ else if (html_node_set_value(p, "Hello from slweb!"))
+ {
+ fprintf(stderr, "%s: html_node_set_value p failed\n", __func__);
+ goto end;
+ }
+ else if (html_serialize(html, &d))
+ {
+ fprintf(stderr, "%s: html_serialize failed\n", __func__);
+ goto end;
+ }
+
+ *r = (const struct http_response)
+ {
+ .status = HTTP_STATUS_OK,
+ .buf.rw = d.str,
+ .n = d.len,
+ .free = free
+ };
+
+ if (http_response_add_header(r, "Content-Type", "text/html"))
+ {
+ fprintf(stderr, "%s: http_response_add_header failed\n", __func__);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ html_node_free(html);
+
+ if (ret)
+ dynstr_free(&d);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ const short port = 8080;
+ const struct handler_cfg cfg = {0};
+ struct handler *const h = handler_alloc(&cfg);
+ static const char *const urls[] = {"/", "/index.html"};
+
+ if (!h)
+ {
+ fprintf(stderr, "%s: handler_alloc failed\n", __func__);
+ goto end;
+ }
+
+ for (size_t i = 0; i < sizeof urls / sizeof *urls; i++)
+ if (handler_add(h, urls[i], HTTP_OP_GET, hello, NULL))
+ {
+ fprintf(stderr, "%s: handler_add failed\n", __func__);
+ goto end;
+ }
+
+ if (handler_listen(h, port))
+ {
+ fprintf(stderr, "%s: handler_listen failed\n", __func__);
+ goto end;
+ }
+
+ ret = EXIT_SUCCESS;
+
+end:
+ handler_free(h);
+ return ret;
+}