1
0
Fork 0

Add hello world example

This commit is contained in:
Xavier Del Campo Romero 2023-08-06 16:43:57 +02:00
parent 83b8b8c2b3
commit 4ee88984fc
Signed by untrusted user: xavi
GPG Key ID: 84FF3612A9BF43F2
9 changed files with 191 additions and 0 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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

2
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,2 @@
cmake_minimum_required(VERSION 3.13)
add_subdirectory(hello)

11
examples/Makefile Normal file
View File

@ -0,0 +1,11 @@
.POSIX:
all: hello
clean:
+cd hello && $(MAKE) clean
FORCE:
hello: FORCE
+cd hello && $(MAKE)

View File

@ -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)

26
examples/hello/Makefile Normal file
View File

@ -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)

17
examples/hello/README.md Normal file
View File

@ -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.

101
examples/hello/main.c Normal file
View File

@ -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;
}