diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-08-06 16:43:57 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-08-09 00:32:13 +0200 |
| commit | 4ee88984fcca86c5b0c9c4bbb7e9148c7d2fe9db (patch) | |
| tree | aa4ab670afd116e419a9661bd266e7c3d0b56dc4 | |
| parent | 83b8b8c2b3622ff7dfc46adf25b6723f1abfb0b5 (diff) | |
Add hello world example
| -rw-r--r-- | CMakeLists.txt | 5 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 19 | ||||
| -rw-r--r-- | examples/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | examples/Makefile | 11 | ||||
| -rw-r--r-- | examples/hello/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | examples/hello/Makefile | 26 | ||||
| -rw-r--r-- | examples/hello/README.md | 17 | ||||
| -rw-r--r-- | examples/hello/main.c | 101 |
9 files changed, 191 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 82d6667..9127b07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.13.5) +option(BUILD_EXAMPLES ON) project(slweb C) add_library(${PROJECT_NAME} handler.c @@ -9,3 +10,7 @@ add_library(${PROJECT_NAME} add_subdirectory(dynstr) target_include_directories(${PROJECT_NAME} PUBLIC include) target_link_libraries(${PROJECT_NAME} PUBLIC dynstr) + +if(BUILD_EXAMPLES) + add_subdirectory(examples) +endif() @@ -16,6 +16,12 @@ all: $(PROJECT) clean: rm -f $(OBJECTS) $(DEPS) + +cd examples && $(MAKE) clean + +FORCE: + +examples: FORCE + +cd examples && $(MAKE) $(PROJECT): $(OBJECTS) $(AR) $(ARFLAGS) $@ $(OBJECTS) @@ -103,6 +103,25 @@ add_subdirectory(slweb) target_link_libraries(${PROJECT_NAME} PRIVATE slweb) ``` +### Examples + +[A directory](examples) with examples shows how `slweb` can be used by +applications. These can be built from the top-level directory with: + +```sh +$ make examples +``` + +In the case of CMake builds, examples are built by default. This can be turned +off by assigning `BUILD_EXAMPLES` to `OFF` or `0`: + +```sh +$ mkdir build/ +$ cd build/ +$ cmake .. -DBUILD_EXAMPLES=OFF +$ cmake --build . +``` + ## Why this project? Originally, `slweb` was part of the diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..1c51e14 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 3.13) +add_subdirectory(hello) diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..4fdbb46 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,11 @@ +.POSIX: + +all: hello + +clean: + +cd hello && $(MAKE) clean + +FORCE: + +hello: FORCE + +cd hello && $(MAKE) 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; +} |
