From dc8b14d99028b9235aa7d7633906a979aa08e4f9 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Date: Fri, 17 Nov 2023 16:34:45 +0100 Subject: Add PUT server example --- .gitignore | 1 + examples/CMakeLists.txt | 1 + examples/Makefile | 3 +- examples/put/CMakeLists.txt | 4 ++ examples/put/Makefile | 26 +++++++++++++ examples/put/README.md | 18 +++++++++ examples/put/main.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 examples/put/CMakeLists.txt create mode 100644 examples/put/Makefile create mode 100644 examples/put/README.md create mode 100644 examples/put/main.c diff --git a/.gitignore b/.gitignore index e39347a..58d8edc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.so.* examples/hello/hello examples/html/html +examples/put/put diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7353458..4c2a6a2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,3 +2,4 @@ cmake_minimum_required(VERSION 3.13) add_subdirectory(headers) add_subdirectory(hello) add_subdirectory(html) +add_subdirectory(put) diff --git a/examples/Makefile b/examples/Makefile index 672f209..6d99b4f 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,8 @@ all: \ headers \ hello \ - html + html \ + put clean: +cd hello && $(MAKE) clean diff --git a/examples/put/CMakeLists.txt b/examples/put/CMakeLists.txt new file mode 100644 index 0000000..200ae28 --- /dev/null +++ b/examples/put/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.13) +project(put C) +add_executable(${PROJECT_NAME} main.c) +target_link_libraries(${PROJECT_NAME} PRIVATE web dynstr) diff --git a/examples/put/Makefile b/examples/put/Makefile new file mode 100644 index 0000000..972208b --- /dev/null +++ b/examples/put/Makefile @@ -0,0 +1,26 @@ +.POSIX: + +PROJECT = put +DEPS = \ + main.o +LIBWEB = ../../libweb.a +DYNSTR = ../../dynstr/libdynstr.a +CFLAGS = -I ../../include -I ../../dynstr/include -g +LIBWEB_FLAGS = -L ../../ -l web +DYNSTR_FLAGS = -L ../../dynstr -l dynstr + +all: $(PROJECT) + +clean: + rm -f $(DEPS) + +FORCE: + +$(PROJECT): $(DEPS) $(LIBWEB) $(DYNSTR) + $(CC) $(LDFLAGS) $(DEPS) $(LIBWEB_FLAGS) $(DYNSTR_FLAGS) -o $@ + +$(LIBWEB): FORCE + +cd ../../ && $(MAKE) + +$(DYNSTR): FORCE + +cd ../../dynstr && $(MAKE) diff --git a/examples/put/README.md b/examples/put/README.md new file mode 100644 index 0000000..afa9191 --- /dev/null +++ b/examples/put/README.md @@ -0,0 +1,18 @@ +# HTTP `PUT` example + +This example shows a minimal setup for an application using `libweb` that only +accepts `PUT` requests. When executed, it starts a HTTP/1.1 server on a random +port that shall be printed to standard output. When a `PUT` request is received, +`libweb` shall store the body into a file in the `/tmp` directory, and print the +path of the temporary file to the standard output. + +## 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/put/main.c b/examples/put/main.c new file mode 100644 index 0000000..cf38248 --- /dev/null +++ b/examples/put/main.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include + +static int on_put(const struct http_payload *const pl, + struct http_response *const r, void *const user) +{ + if (pl->expect_continue) + { + *r = (const struct http_response) + { + .status = HTTP_STATUS_CONTINUE + }; + + return 0; + } + + printf("File uploaded to %s\n", pl->u.put.tmpname); + + *r = (const struct http_response) + { + .status = HTTP_STATUS_OK + }; + + return 0; +} + +static int on_length(const unsigned long long len, + const struct http_cookie *const c, struct http_response *const r, + void *const user) +{ + *r = (const struct http_response) + { + .status = HTTP_STATUS_OK + }; + + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret = EXIT_FAILURE; + const struct handler_cfg cfg = + { + .tmpdir = "/tmp", + .length = on_length + }; + + struct handler *const h = handler_alloc(&cfg); + static const char *const urls[] = {"/*"}; + + 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_PUT, on_put, NULL)) + { + fprintf(stderr, "%s: handler_add failed\n", __func__); + goto end; + } + + unsigned short outport; + + if (handler_listen(h, 0, &outport)) + { + fprintf(stderr, "%s: handler_listen failed\n", __func__); + goto end; + } + + printf("Listening on port %hu\n", outport); + + if (handler_loop(h)) + { + fprintf(stderr, "%s: handler_loop failed\n", __func__); + goto end; + } + + ret = EXIT_SUCCESS; + +end: + handler_free(h); + return ret; +} -- cgit v1.2.3