From d2eaecc786e387c7c2c8d5367589ebb8e70708bf Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 10 Oct 2022 21:49:48 +0300 Subject: [PATCH 1/9] fastcgi server is separated from the main library and is now optional --- .clangd | 11 ++- Makefile | 8 +- README.md | 5 +- c/app.c | 110 ++--------------------- c/request.c | 40 --------- c/response.c | 14 ++- config.mk | 14 ++- docs/src/index.dox | 2 +- examples/c/example.c | 5 +- examples/c/minimal.c | 5 +- examples/cxx/example.cxx | 5 +- examples/cxx/minimal.cxx | 6 +- include/App.hxx | 24 +++-- include/Query.hxx | 6 +- include/app.h | 12 +-- include/request.h | 3 - include/response.h | 15 ++-- include/servers/fcgi.h | 31 +++++++ servers/fcgi.c | 185 +++++++++++++++++++++++++++++++++++++++ 19 files changed, 290 insertions(+), 211 deletions(-) create mode 100644 include/servers/fcgi.h create mode 100644 servers/fcgi.c diff --git a/.clangd b/.clangd index 3bcc16d..2a1dc75 100644 --- a/.clangd +++ b/.clangd @@ -1,7 +1,12 @@ CompileFlags: - Add: [-Wall, -pedantic, -I../include, -DEXTENSIONS_INJA, - -DDIST_PATH="/var/www/html"] - + Add: + - -Wall + - -pedantic + - -I../include + - -DMT_ENABLED + - -DNTHREADS=8 + - -DEXTENSIONS_INJA, + - -DDIST_PATH="/var/www/html" --- # Specific C sources diff --git a/Makefile b/Makefile index f71e12c..89ac9c6 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ include config.mk CXXSRC := $(shell find cxx -type f -name '*.cxx') CSRC += $(shell find c -type f -name '*.c') +ifeq ($(FCGI_SERVER), 1) + CSRC += servers/fcgi.c +endif + CXXOBJ := $(CXXSRC:.cxx=.o) COBJ := $(CSRC:.c=.o) @@ -82,9 +86,7 @@ docs: #target Format code format: - clang-format -Werror -i $(CSRC) $(CXXSRC) - clang-format -Werror -i examples/*.c* - clang-format -Werror -i tests/*.c* tests/*.h* + clang-format -Werror -i **/*.c* **/*.h* #target Show this help help: diff --git a/README.md b/README.md index 0cca31f..d4f1182 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,13 @@ Rapida ====== [![Build Status](http://drone.vilor.one/api/badges/Rapida/rapida/status.svg)](http://drone.vilor.one/Rapida/rapida) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[Documentation](http://rapida.vilor.one/docs) -Rapida is the C and C++ web framework based on FastCGI protocol. +Web framework written in C and C++. Dependencies ------------ -* libfcgi +* libfcgi (if you need a FastCGI server) * doxygen (to make docs) * catch2 (to run tests) diff --git a/c/app.c b/c/app.c index 27922a6..3bd8482 100644 --- a/c/app.c +++ b/c/app.c @@ -5,24 +5,6 @@ #include #include -#ifdef MT_ENABLED -#include -#endif /* MT_ENABLED */ - -/*! - * \brief Listens new requests by FastCGI protocol. - * \param app Pointer to current App instance. - * \return Always returns NULL. - */ -static void *listen_requests(void *app); - -/*! - * Handle accepted request. - * \param app Application instance. - * \param req FastCGI request. - */ -static void handle_request(rpd_app *app, FCGX_Request *fcgx_req); - /*! * \brief Selects a route handler based on requested path. * \param app Application instance. @@ -31,36 +13,10 @@ static void handle_request(rpd_app *app, FCGX_Request *fcgx_req); */ static rpd_route *routes_fabric(rpd_app *app, rpd_req *req); -int rpd_app_create(rpd_app *app, const char *sock_path) +int rpd_app_create(rpd_app *app) { - app->running = app->sock_id = app->routes_len = 0; + app->running = app->routes_len = 0; app->routes = NULL; - - app->sock_path = strdup(sock_path); - if (!app->sock_path) - return 1; - - FCGX_Init(); - - return 0; -} - -int rpd_app_start(rpd_app *app) -{ - if ((app->sock_id = FCGX_OpenSocket(app->sock_path, 10)) < 0) { - return 1; - } - -#ifdef MT_ENABLED - pthread_t threads[NTHREADS]; - for (int i = 0; i < NTHREADS; i++) { - pthread_create(&threads[i], 0, listen_requests, (void *) app); - pthread_join(threads[i], 0); - } -#else - listen_requests((void *) app); -#endif - return 0; } @@ -79,69 +35,15 @@ int rpd_app_add_route(rpd_app *app, const char *path, rpd_route_cb cb, return 0; } -static void *listen_requests(void *userdata) +void rpd_app_handle_request(rpd_app *app, rpd_req *req, rpd_res *res) { - rpd_app *app = (rpd_app *) userdata; - - FCGX_Request req; - if (FCGX_InitRequest(&req, app->sock_id, 0)) { - return 0; - } - - app->running = 1; - while (app->running) { -#ifdef MT_ENABLED - static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&accept_mutex); -#endif - - int rc = FCGX_Accept_r(&req); - -#ifdef MT_ENABLED - pthread_mutex_unlock(&accept_mutex); -#endif - - if (rc < 0) { - break; - } - -#ifdef MT_ENABLED - static pthread_mutex_t handle_mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&handle_mutex); -#endif - - handle_request(app, &req); - -#ifdef MT_ENABLED - pthread_mutex_unlock(&handle_mutex); -#endif - - FCGX_Finish_r(&req); - } - - return 0; -} - -static void handle_request(rpd_app *app, FCGX_Request *fcgx_req) -{ - rpd_req req; - rpd_res res; - - rpd_req_parse(&req, fcgx_req); - rpd_res_init(&res, fcgx_req); - - // get route and process request - rpd_route *route = routes_fabric(app, &req); + rpd_route *route = routes_fabric(app, req); if (!route) { + res->status = rpd_res_st_not_found; return; } - route->cb(&req, &res, route->userdata); - - rpd_res_send(&res); - - rpd_req_cleanup(&req); - rpd_res_cleanup(&res); + route->cb(req, res, route->userdata); } static rpd_route *routes_fabric(rpd_app *app, rpd_req *req) diff --git a/c/request.c b/c/request.c index 3d242ed..c1d45c5 100644 --- a/c/request.c +++ b/c/request.c @@ -5,8 +5,6 @@ #include #include -static int rpd_req_read_body(char **dest, FCGX_Request *req); - enum rpd_req_methods rpd_req_smethod(const char *method) { if (!strcmp(method, "GET")) @@ -30,44 +28,6 @@ enum rpd_req_methods rpd_req_smethod(const char *method) return UNKNOWN; } -int rpd_req_parse(rpd_req *dest, FCGX_Request *req) -{ - rpd_query_parse(&dest->query, FCGX_GetParam("QUERY_STRING", req->envp)); - - dest->method = rpd_req_smethod(FCGX_GetParam("REQUEST_METHOD", req->envp)); - rpd_url_parse(&dest->path, FCGX_GetParam("DOCUMENT_URI", req->envp)); - dest->auth = FCGX_GetParam("HTTP_AUTHORIZATION", req->envp); - dest->cookie = FCGX_GetParam("HTTP_COOKIE", req->envp); - rpd_keyval_init(&dest->params, 0); - - if (dest->method != GET) { - if (rpd_req_read_body(&dest->body, req)) { - return 2; - } - } else { - dest->body = NULL; - } - - return 0; -} - -static int rpd_req_read_body(char **dest, FCGX_Request *req) -{ - char *clen = FCGX_GetParam("CONTENT_LENGTH", req->envp); - if (!clen) - return 1; - size_t len = atoll(clen); - - *dest = (char *) malloc(sizeof(char) * (len + 1)); - if (!*dest) - return 2; - - *dest[len] = '\0'; - FCGX_GetStr(*dest, len, req->in); - - return 0; -} - void rpd_req_cleanup(rpd_req *req) { rpd_keyval_cleanup(&req->params); diff --git a/c/response.c b/c/response.c index eaf1897..2bd1e7d 100644 --- a/c/response.c +++ b/c/response.c @@ -8,10 +8,8 @@ static size_t calc_res_buff_sz(const rpd_res *res); -void rpd_res_init(rpd_res *dest, FCGX_Request *req) +void rpd_res_init(rpd_res *dest) { - dest->out = req->out; - dest->status = rpd_res_st_ok; dest->location = dest->content_type = NULL; dest->body = NULL; @@ -19,17 +17,17 @@ void rpd_res_init(rpd_res *dest, FCGX_Request *req) rpd_keyval_init(&dest->cookie, 0); } -int rpd_res_send(rpd_res *res) +int rpd_res_str(char **dest, const rpd_res *res) { size_t size = calc_res_buff_sz(res); - char *buff = (char *) malloc(sizeof(char) * size); - if (!buff) { + *dest = (char *) malloc(sizeof(char) * size); + if (!*dest) { return 1; } /* header */ - char *ptr = buff; + char *ptr = *dest; ptr += sprintf(ptr, "Status: %d\r\n", res->status); if (res->content_type) { @@ -50,8 +48,6 @@ int rpd_res_send(rpd_res *res) ptr += bodylen; } - FCGX_PutS(buff, res->out); - free(buff); return 0; } diff --git a/config.mk b/config.mk index 98f2e04..c28750c 100644 --- a/config.mk +++ b/config.mk @@ -1,4 +1,4 @@ -VERSION=0.2.1 +VERSION=0.2.2 #arg Installation prefix PREFIX=/usr/local @@ -7,7 +7,7 @@ CFLAGS=-std=gnu99 -pedantic -Iinclude CXX=c++ CXXFLAGS=-pedantic -Iinclude CXXSTD=-ansi -LDFLAGS=-lfcgi +LDFLAGS= #flag Debug mode DEBUG ?= 0 @@ -19,14 +19,12 @@ else CXXFLAGS+=-O3 endif - -#arg Additional CXX flags -ADD_CXXFLAGS = -ifdef ADD_CXXFLAGS - CXXFLAGS+=$(ADD_CXXFLAGS) +#flag Add FastCGI server +FCGI_SERVER ?= 1 +ifeq ($(FCGI_SERVER), 1) + LDFLAGS += -lfcgi endif - #flag Enable inja extension EXTENSIONS_INJA ?= 0 #arg Dist path. Needed only if inja is enabled. diff --git a/docs/src/index.dox b/docs/src/index.dox index 53fffec..a311f28 100644 --- a/docs/src/index.dox +++ b/docs/src/index.dox @@ -2,7 +2,7 @@ \mainpage Rapida Manual -Rapida is the fast web framework written in C and C++. +Web framework written in C and C++. Table of contents: 1. \subpage get_started diff --git a/examples/c/example.c b/examples/c/example.c index a5d9e3a..e071506 100644 --- a/examples/c/example.c +++ b/examples/c/example.c @@ -1,4 +1,5 @@ #include "../../include/rapida.h" +#include "../../include/servers/fcgi.h" #include #include #include @@ -47,10 +48,10 @@ static void products_handler(rpd_req *req, rpd_res *res, void *userdata) int main() { rpd_app app; - rpd_app_create(&app, "/tmp/rapida.example.socket"); + rpd_app_create(&app); rpd_app_add_route(&app, "/products/:category/:id", &products_handler, NULL); - rpd_app_start(&app); + return rpd_fcgi_server_start(&app, "/tmp/webapp.socket"); return 0; } diff --git a/examples/c/minimal.c b/examples/c/minimal.c index 7db18d8..536292b 100644 --- a/examples/c/minimal.c +++ b/examples/c/minimal.c @@ -1,4 +1,5 @@ #include "../../include/rapida.h" +#include "../../include/servers/fcgi.h" #include /* for strdup() */ #include @@ -44,11 +45,11 @@ int main() { rpd_app app; /* Initialize application. */ - rpd_app_create(&app, "/tmp/webapp.socket"); + rpd_app_create(&app); /* Add home "/" page handler. */ rpd_app_add_route(&app, "/", &home_page_handler, NULL); /* Run the application and return its status code. */ - return rpd_app_start(&app); + return rpd_fcgi_server_start(&app, "/tmp/webapp.socket"); } diff --git a/examples/cxx/example.cxx b/examples/cxx/example.cxx index dd2d42a..2742e9c 100644 --- a/examples/cxx/example.cxx +++ b/examples/cxx/example.cxx @@ -1,4 +1,5 @@ #include "../../include/rapida.hxx" +#include "../../include/servers/fcgi.h" #include class ProductRoute : public rpd::Route { @@ -40,7 +41,7 @@ protected: int main() { - rpd::App app("/tmp/rapida.example.socket"); + rpd::App app; /* * `category` and `id` are dynamic parameters @@ -48,5 +49,5 @@ int main() */ app.add_route("/products/:category/:id", new ProductRoute()); - return app.start(); + return rpd_fcgi_server_start(app.c_app(), "/tmp/webapp.socket"); } diff --git a/examples/cxx/minimal.cxx b/examples/cxx/minimal.cxx index 4ab8d02..fa98c1b 100644 --- a/examples/cxx/minimal.cxx +++ b/examples/cxx/minimal.cxx @@ -1,4 +1,6 @@ #include "../../include/rapida.hxx" +#include "../../include/servers/fcgi.h" + /* * \brief Home page route handler. @@ -33,9 +35,9 @@ protected: int main() { - rpd::App app("/tmp/webapp.socket"); + rpd::App app; app.add_route("/", new Home()); - return app.start(); + return rpd_fcgi_server_start(app.c_app(), "/tmp/webapp.socket"); } diff --git a/include/App.hxx b/include/App.hxx index 2cb3db3..b31a63d 100644 --- a/include/App.hxx +++ b/include/App.hxx @@ -17,28 +17,24 @@ class App { public: /*! * Creates an rpd app and initializes FastCGI. - * \brief Constructor + * \brief Default constructor * \param socket_path UNIX Socket path. */ - App(const char *const socket_path) + App() { - rpd_app_create(&app, socket_path); + rpd_app_create(&app); } /*! - * \brief Starts the requests handling loop. - */ - int start() - { - return rpd_app_start(&app); - } - - /*! - * \brief Stops the requests handling loop. + * \brief Returns C implementation of the application. + * + * Usable when you need to start C server. + * + * \return C implementation of the application. */ - void stop() + rpd_app *c_app() const { - app.running = false; + return (rpd_app *) &app; } /*! diff --git a/include/Query.hxx b/include/Query.hxx index 8cfbf4b..81e54e7 100644 --- a/include/Query.hxx +++ b/include/Query.hxx @@ -20,7 +20,8 @@ public: */ Query() : KeyVal() - {} + { + } /*! * \brief Constructor. @@ -31,7 +32,8 @@ public: */ Query(rpd_keyval *keyval) : KeyVal(keyval) - {} + { + } /*! * \brief Parse query string into the key-val pairs. diff --git a/include/app.h b/include/app.h index adf4666..7475f1c 100644 --- a/include/app.h +++ b/include/app.h @@ -19,8 +19,6 @@ extern "C" { */ typedef struct { int running; /**< Application will be running while this flag is true. */ - const char *sock_path; /**< Application UNIX Socket path. */ - int sock_id; /**< Application UNIX Socket id. */ int routes_len; /**< Length of the rpd_app::routes array. */ rpd_route *routes; /**< Array of the active routes. */ } rpd_app; @@ -29,19 +27,17 @@ typedef struct { * \brief Creates Rapida application. * * \param app Pointer to application instance. - * \param sock_path UNIX Socket path. * * \return Status. 0 is success. */ -int rpd_app_create(rpd_app *app, const char *sock_path); +int rpd_app_create(rpd_app *app); /*! - * \brief Starts Rapida main loop. + * Handle accepted request. * \param app Application instance. - * - * \return Status. 0 is success. + * \param req FastCGI request. */ -int rpd_app_start(rpd_app *app); +void rpd_app_handle_request(rpd_app *app, rpd_req *req, rpd_res *res); /*! * \brief Adds route to application. diff --git a/include/request.h b/include/request.h index c47d736..af3eca3 100644 --- a/include/request.h +++ b/include/request.h @@ -10,7 +10,6 @@ #include "query.h" #include "url.h" -#include #ifdef __cplusplus extern "C" { @@ -45,8 +44,6 @@ typedef struct { rpd_keyval params; /**< Dynamic parameters. */ } rpd_req; -int rpd_req_parse(rpd_req *dest, FCGX_Request *req); - /*! * \brief Parser string request method to enumeration value. * diff --git a/include/response.h b/include/response.h index b407276..c567797 100644 --- a/include/response.h +++ b/include/response.h @@ -9,7 +9,7 @@ #define RAPIDA_RESPONSE_H_ENTRY #include "keyval.h" -#include +#include "request.h" #ifdef __cplusplus extern "C" { @@ -86,7 +86,6 @@ enum rpd_res_statuses { */ typedef struct { enum rpd_res_statuses status; /**< Response status code. */ - FCGX_Stream *out; /**< Output stream. */ char *location; /**< Location field. */ char *content_type; /**< Content type. */ char *body; /**< Response body. */ @@ -99,13 +98,17 @@ typedef struct { * \param dest Response instance. * \param req FastCGI request. */ -void rpd_res_init(rpd_res *dest, FCGX_Request *req); +void rpd_res_init(rpd_res *dest); /*! - * \brief Sends response to client. - * \param res Response instance. + * \brief Write response to string buffer. + * + * \param dest Destination buffer. + * \param src Response. + * + * \return Status code. 0 is succes. */ -int rpd_res_send(rpd_res *res); +int rpd_res_str(char **dest, const rpd_res *src); /*! * \brief Cleans response instance. diff --git a/include/servers/fcgi.h b/include/servers/fcgi.h new file mode 100644 index 0000000..d0acf5f --- /dev/null +++ b/include/servers/fcgi.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* Copyright 2022 Ivan Polyakov */ + +/*! + * \file fcgi.h + * \brief Rapida FastCGI server + */ +#ifndef RAPIDA_SERVERS_FCGI_H_ENTRY +#define RAPIDA_SERVERS_FCGI_H_ENTRY + +#include "../app.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief Starts Rapida FastCGI server. + * \param app Application instance. + * \param sock_path UNIX Socket path. + * + * \return Status. 0 is success. + */ +int rpd_fcgi_server_start(rpd_app *app, const char *sock_path); + +#ifdef __cplusplus +} +#endif + +#endif /* RAPIDA_SERVERS_FCGI_H_ENTRY */ diff --git a/servers/fcgi.c b/servers/fcgi.c new file mode 100644 index 0000000..d02579a --- /dev/null +++ b/servers/fcgi.c @@ -0,0 +1,185 @@ +#include "../include/servers/fcgi.h" +#include + +#ifdef MT_ENABLED +#include +#endif /* MT_ENABLED */ + +typedef struct { + rpd_app *app; + int sock_id; +} thread_data; + +/*! + * \brief Run FastCGI requests listening in loop. + * \param data \see thread_data. + * \return NULL; + */ +static void *listen_requests(void *data); + +/*! + * \brief Handle Request. + * + * This function converts FastCGI request into the Rapida request + * and calls Rapida request handler. + * + * \param app Application instance. + * \param fcgx_req FastCGI Request. + */ +static void handle_request(rpd_app *app, FCGX_Request *fcgx_req); + +/*! + * \brief Convert FastCGI request into the Rapida request. + * + * \param dest Rapida request. + * \param req FastCGI request. + * + * \return Status code. 0 is success. + */ +static int fcgx_to_rpd_req(rpd_req *dest, FCGX_Request *req); + +/*! + * Read FastCGI request body. + * \param dest Destination buffer. + * \param req FastCGI request. + * \return Status code. 0 is success. + */ +static int read_fcgx_req_body(char **dest, FCGX_Request *req); + +/*! + * \brief Sends response to client. + * \param res Response instance. + * \param out Output stream. + */ +static void send_response(rpd_res *res, FCGX_Stream *out); + +int rpd_fcgi_server_start(rpd_app *app, const char *sock_path) +{ + FCGX_Init(); + int sock_id = 0; + if ((sock_id = FCGX_OpenSocket(sock_path, 10)) < 0) { + return 1; + } + + thread_data data = { app, sock_id }; +#ifdef MT_ENABLED + pthread_t threads[NTHREADS]; + for (int i = 0; i < NTHREADS; i++) { + pthread_create(&threads[i], 0, &listen_requests, (void *) &data); + pthread_join(threads[i], 0); + } +#else + listen_requests((void *) &data); +#endif + + return 0; +} + +static void *listen_requests(void *data) +{ + thread_data *hdata = (thread_data *) data; + FCGX_Request req; + if (FCGX_InitRequest(&req, hdata->sock_id, 0)) + return 0; + + hdata->app->running = 1; + while (hdata->app->running) { +#ifdef MT_ENABLED + static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&accept_mutex); +#endif + + int rc = FCGX_Accept_r(&req); + +#ifdef MT_ENABLED + pthread_mutex_unlock(&accept_mutex); +#endif + + if (rc < 0) + break; + +#ifdef MT_ENABLED + static pthread_mutex_t handle_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&handle_mutex); +#endif + + handle_request(hdata->app, &req); + +#ifdef MT_ENABLED + pthread_mutex_unlock(&handle_mutex); +#endif + + FCGX_Finish_r(&req); + } + return NULL; +} + +static void handle_request(rpd_app *app, FCGX_Request *fcgx_req) +{ + rpd_req *req; + rpd_res *res; + + req = (rpd_req *) malloc(sizeof(rpd_req)); + res = (rpd_res *) malloc(sizeof(rpd_res)); + + fcgx_to_rpd_req(req, fcgx_req); + rpd_res_init(res); + + rpd_app_handle_request(app, req, res); + send_response(res, fcgx_req->out); + + rpd_req_cleanup(req); + rpd_res_cleanup(res); + free(req); + free(res); +} + +static void send_response(rpd_res *res, FCGX_Stream *out) +{ + char *buff; + if (rpd_res_str(&buff, res)) { + FCGX_PutS("Status: 500\r\n\r\n", out); + return; + } + + FCGX_PutS(buff, out); + free(buff); +} + +static int fcgx_to_rpd_req(rpd_req *dest, FCGX_Request *req) +{ + rpd_query_parse(&dest->query, FCGX_GetParam("QUERY_STRING", req->envp)); + + dest->method = rpd_req_smethod(FCGX_GetParam("REQUEST_METHOD", req->envp)); + rpd_url_parse(&dest->path, FCGX_GetParam("DOCUMENT_URI", req->envp)); + dest->auth = FCGX_GetParam("HTTP_AUTHORIZATION", req->envp); + dest->cookie = FCGX_GetParam("HTTP_COOKIE", req->envp); + rpd_keyval_init(&dest->params, 0); + + if (dest->method != GET) { + if (read_fcgx_req_body(&dest->body, req)) { + return 2; + } + } else { + dest->body = NULL; + } + + return 0; +} + +static int read_fcgx_req_body(char **dest, FCGX_Request *req) +{ + char *clen = FCGX_GetParam("CONTENT_LENGTH", req->envp); + if (!clen) + return 1; + size_t len = atoll(clen); + + *dest = (char *) malloc(sizeof(char) * (len + 1)); + if (!*dest) + return 2; + + *dest[len] = '\0'; + FCGX_GetStr(*dest, len, req->in); + + return 0; +} From 0c4532831ae2aa54e4447c6f7789ee7867275797 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 10 Oct 2022 21:55:47 +0300 Subject: [PATCH 2/9] fixed compilation of server module --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 89ac9c6..e000e7e 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,9 @@ librapida.a: $(COBJ) librapidaxx.a: $(COBJ) $(CXXOBJ) ar rvs $@ $^ +servers/%.o: servers/%.c + $(CC) $(CFLAGS) -fPIC $< -c -o $@ + c/%.o: c/%.c $(CC) $(CFLAGS) -fPIC $< -c -o $@ From 0c653de29a23e2a55248a6b6ae32b53c98477326 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Tue, 18 Oct 2022 18:25:22 +0300 Subject: [PATCH 3/9] "install" target fixed --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e000e7e..003c797 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ install: all ln -s $(PREFIX)/lib/librapida.so.$(VERSION) $(PREFIX)/lib/librapida.so ln -s $(PREFIX)/lib/librapidaxx.so.$(VERSION) $(PREFIX)/lib/librapidaxx.so mkdir -p $(PREFIX)/include/rapida - cp -f include/* $(PREFIX)/include/rapida + cp -rf include/* $(PREFIX)/include/rapida uninstall: rm -f $(PREFIX)/lib/librapida.a From 89e93a588bd230fe7f42dedb64f080c45be34f76 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Tue, 18 Oct 2022 18:25:52 +0300 Subject: [PATCH 4/9] readme upd --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d4f1182..c8871f4 100644 --- a/README.md +++ b/README.md @@ -12,20 +12,23 @@ Dependencies * doxygen (to make docs) * catch2 (to run tests) -Extensions ----------- -* [inja](https://github.com/pantor/inja) (template rendering, - requires [nlohmann/json](https://github.com/nlohmann/json)) - -Building --------- +Installation +------------ You need: * GNU Make * C compiler with C99 support * C++ compiler with C++98 and C++17 support +```sh +make install clean +``` Run `make help` to see targets, flags and arguments. +Extensions +---------- +* [inja](https://github.com/pantor/inja) (template rendering, + requires [nlohmann/json](https://github.com/nlohmann/json)) + Examples -------- See [examples](examples). From 5751e17f985d4048d47791898b6c7977baa16ffa Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Wed, 19 Oct 2022 22:01:49 +0300 Subject: [PATCH 5/9] c code rewritten to c99 without gnu extensions --- .clangd | 2 +- c/keyval.c | 5 +++-- c/query.c | 8 ++++---- c/url.c | 10 +++++----- c/utils.c | 29 +++++++++++++++++++++++++++++ c/utils.h | 4 ++++ config.mk | 2 +- 7 files changed, 47 insertions(+), 13 deletions(-) diff --git a/.clangd b/.clangd index 2a1dc75..e343b1b 100644 --- a/.clangd +++ b/.clangd @@ -13,7 +13,7 @@ CompileFlags: If: PathMatch: [.*\.c, .*\.h] CompileFlags: - Add: [-std=gnu99] + Add: [-std=c99] --- diff --git a/c/keyval.c b/c/keyval.c index 23d99cb..0a17d06 100644 --- a/c/keyval.c +++ b/c/keyval.c @@ -2,6 +2,7 @@ /* Copyright 2022 Ivan Polyakov */ #include "keyval.h" +#include "utils.h" #include #include #include @@ -57,8 +58,8 @@ int rpd_keyval_insert(rpd_keyval *keyval, const char *key, const char *value) keyval->size++; } - item->key = strdup(key); - item->val = strdup(value); + item->key = rpd_strdup(key); + item->val = rpd_strdup(value); return item->key && item->val ? 0 : 2; } diff --git a/c/query.c b/c/query.c index 1219e98..7515bd8 100644 --- a/c/query.c +++ b/c/query.c @@ -17,7 +17,7 @@ int rpd_query_parse(rpd_keyval *dest, const char *src) return 0; } - char *query = strdup(src); + char *query = rpd_strdup(src); if (!query) return 1; @@ -28,7 +28,7 @@ int rpd_query_parse(rpd_keyval *dest, const char *src) char *tokens = query, *p = query; int i = 0; - while ((p = strsep(&tokens, "&\n")) && i < len) { + while ((p = rpd_strsep(&tokens, "&\n")) && i < len) { char *param, *val; if (*p == '=') @@ -37,8 +37,8 @@ int rpd_query_parse(rpd_keyval *dest, const char *src) val = strtok(NULL, "="); if (param) { - dest->items[i].key = strdup(param); - dest->items[i].val = val ? strdup(val) : NULL; + dest->items[i].key = rpd_strdup(param); + dest->items[i].val = val ? rpd_strdup(val) : NULL; i++; } } diff --git a/c/url.c b/c/url.c index e7b5046..9cf99cf 100644 --- a/c/url.c +++ b/c/url.c @@ -23,11 +23,11 @@ int rpd_url_parse(rpd_url *dest, const char *src) i = 0; char *tmp, *token; - tmp = strdup(src); - while ((token = strsep(&tmp, "/"))) { + tmp = rpd_strdup(src); + while ((token = rpd_strsep(&tmp, "/"))) { if (!strlen(token)) continue; - dest->parts[i] = strdup(token); + dest->parts[i] = rpd_strdup(token); i++; } free(tmp); @@ -65,7 +65,7 @@ int rpd_url_params_parse_keys(rpd_keyval *dest, const rpd_url *tpl) for (int i = 0; i < tpl->parts_len; i++) { if (*tpl->parts[i] == ':') { - dest->items[dest->size].key = strdup(tpl->parts[i] + 1); + dest->items[dest->size].key = rpd_strdup(tpl->parts[i] + 1); dest->size++; } } @@ -78,7 +78,7 @@ int rpd_url_params_parse_vals(rpd_keyval *dest, const rpd_url *url, const rpd_ur int i = 0, j = 0; while (i < tpl->parts_len) { if (*tpl->parts[i] == ':') { - dest->items[j++].val = strdup(url->parts[i]); + dest->items[j++].val = rpd_strdup(url->parts[i]); } i++; } diff --git a/c/utils.c b/c/utils.c index fb2762b..174ed2a 100644 --- a/c/utils.c +++ b/c/utils.c @@ -2,6 +2,8 @@ /* Copyright 2022 Ivan Polyakov */ #include "utils.h" +#include +#include int count_char_entries(const char *str, char ch) { @@ -14,3 +16,30 @@ int count_char_entries(const char *str, char ch) } return cnt; } + +char *rpd_strdup(const char *src) +{ + size_t size = strlen(src) + 1; + char *dest = (char *) malloc(sizeof(char) * size); + if (!dest) { + return NULL; + } + return memcpy(dest, src, size); +} + +char *rpd_strsep(char **str, const char *sep) +{ + char *s = *str, *end; + if (!s) { + return NULL; + } + + end = s + strcspn(s, sep); + if (*end) { + *end++ = 0; + } else { + end = 0; + } + *str = end; + return s; +} diff --git a/c/utils.h b/c/utils.h index 2ca2d9c..53c6430 100644 --- a/c/utils.h +++ b/c/utils.h @@ -6,4 +6,8 @@ int count_char_entries(const char *str, char ch); +char *rpd_strdup(const char *src); + +char *rpd_strsep(char **str, const char *sep); + #endif /* RAPIDA_UTILS_H_ENTRY */ diff --git a/config.mk b/config.mk index c28750c..9f9c983 100644 --- a/config.mk +++ b/config.mk @@ -3,7 +3,7 @@ VERSION=0.2.2 PREFIX=/usr/local CC=gcc -CFLAGS=-std=gnu99 -pedantic -Iinclude +CFLAGS=-std=c99 -pedantic -Iinclude CXX=c++ CXXFLAGS=-pedantic -Iinclude CXXSTD=-ansi From 3745d2003a497612b1a316354792e6c5340e42b8 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 31 Oct 2022 19:57:26 +0300 Subject: [PATCH 6/9] tcp server --- Makefile | 3 ++ README.md | 1 + c/response.c | 51 +++++++++++++++----- config.mk | 10 +++- docs/src/development.dox | 2 + docs/src/get_started.dox | 17 +++++++ docs/src/index.dox | 8 +-- examples/c/example.c | 5 +- examples/c/minimal.c | 9 ++-- examples/cxx/example.cxx | 4 +- examples/cxx/minimal.cxx | 4 +- include/App.hxx | 3 +- include/Response.hxx | 1 - include/app.h | 3 +- include/response.h | 13 ++++- include/servers/tcp.h | 30 ++++++++++++ servers/fcgi.c | 3 ++ servers/tcp.c | 102 +++++++++++++++++++++++++++++++++++++++ 18 files changed, 232 insertions(+), 37 deletions(-) create mode 100644 include/servers/tcp.h create mode 100644 servers/tcp.c diff --git a/Makefile b/Makefile index 003c797..12a3ebe 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ include config.mk CXXSRC := $(shell find cxx -type f -name '*.cxx') CSRC += $(shell find c -type f -name '*.c') +ifeq ($(TCP_SERVER), 1) + CSRC += servers/tcp.c +endif ifeq ($(FCGI_SERVER), 1) CSRC += servers/fcgi.c endif diff --git a/README.md b/README.md index c8871f4..9844b1d 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Web framework written in C and C++. Dependencies ------------ +* mongoose (if you need a TCP server) * libfcgi (if you need a FastCGI server) * doxygen (to make docs) * catch2 (to run tests) diff --git a/c/response.c b/c/response.c index 2bd1e7d..66c963a 100644 --- a/c/response.c +++ b/c/response.c @@ -6,7 +6,7 @@ #include #include -static size_t calc_res_buff_sz(const rpd_res *res); +static size_t calc_res_headers_sz(const rpd_res *res); void rpd_res_init(rpd_res *dest) { @@ -17,27 +17,54 @@ void rpd_res_init(rpd_res *dest) rpd_keyval_init(&dest->cookie, 0); } +int rpd_res_headers_str(char **dest, const rpd_res *src) +{ + size_t size = calc_res_headers_sz(src); + char *ptr; + + *dest = (char *) malloc(sizeof(char) * size); + if (!*dest) { + perror("malloc"); + return 1; + } + + ptr = *dest; + if (src->content_type) { + ptr += sprintf(ptr, "Content-Type: %s\r\n", src->content_type); + } + + if (src->location) { + ptr += sprintf(ptr, "Location: %s\r\n", src->location); + } + + return 0; +} + int rpd_res_str(char **dest, const rpd_res *res) { - size_t size = calc_res_buff_sz(res); + size_t headers_size, size; + char *ptr, *headers; + size = headers_size = calc_res_headers_sz(res); + if (res->body) + size += 2 + strlen(res->body); *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { + perror("malloc"); return 1; } /* header */ - char *ptr = *dest; + ptr = *dest; ptr += sprintf(ptr, "Status: %d\r\n", res->status); - if (res->content_type) { - ptr += sprintf(ptr, "Content-Type: %s\r\n", res->content_type); - } - - if (res->location) { - ptr += sprintf(ptr, "Location: %s\r\n", res->location); + if (rpd_res_headers_str(&headers, res)) { + return 1; } + memcpy(ptr, headers, headers_size); + free(headers); + ptr += headers_size; memcpy(ptr, "\r\n", 2); ptr += 2; @@ -51,9 +78,9 @@ int rpd_res_str(char **dest, const rpd_res *res) return 0; } -static size_t calc_res_buff_sz(const rpd_res *res) +static size_t calc_res_headers_sz(const rpd_res *res) { - size_t size = res->body ? strlen(res->body) + 2 : 0; + size_t size = 0; size += strlen("Status: \r\n") + 3; if (res->location) { @@ -72,8 +99,6 @@ static size_t calc_res_buff_sz(const rpd_res *res) } } - size += 2; - return size; } diff --git a/config.mk b/config.mk index 9f9c983..707cb00 100644 --- a/config.mk +++ b/config.mk @@ -1,9 +1,9 @@ -VERSION=0.2.2 +VERSION=0.3.0 #arg Installation prefix PREFIX=/usr/local CC=gcc -CFLAGS=-std=c99 -pedantic -Iinclude +CFLAGS=-std=c99 -pedantic -Iinclude -DRPD_VERSION=\"$(VERSION)\" CXX=c++ CXXFLAGS=-pedantic -Iinclude CXXSTD=-ansi @@ -19,6 +19,12 @@ else CXXFLAGS+=-O3 endif +#flag Add TCP server +TCP_SERVER ?= 1 +ifeq ($(TCP_SERVER), 1) + LDFLAGS += -lmongoose +endif + #flag Add FastCGI server FCGI_SERVER ?= 1 ifeq ($(FCGI_SERVER), 1) diff --git a/docs/src/development.dox b/docs/src/development.dox index bcae8c2..5aea286 100644 --- a/docs/src/development.dox +++ b/docs/src/development.dox @@ -2,6 +2,8 @@ \page development Development +[TOC] + Overview -------- We use: diff --git a/docs/src/get_started.dox b/docs/src/get_started.dox index 1986fcb..24ac1f2 100644 --- a/docs/src/get_started.dox +++ b/docs/src/get_started.dox @@ -2,6 +2,8 @@ \page get_started Get Started +[TOC] + Installation ------------ Run the following commands: @@ -37,4 +39,19 @@ gcc myapp.c -lrapida # link C library g++ myapp.cxx -lrapidaxx # link C++ library ``` +Servers +------- +Rapida has focused on the implementation of the framework, +and servers are logically separated form the core. +By default, when you building Rapida, all servers will be linked +to the library, but you can change this by setting the _make_ flags. + +For example, to disable FastCGI server, you need to pass `FCGI_SERVER=0` +flag to `make` command like this: +```sh +make FCGI_SERVER=0 +``` + +To see other flags you can run `make help`. + */ diff --git a/docs/src/index.dox b/docs/src/index.dox index a311f28..709885b 100644 --- a/docs/src/index.dox +++ b/docs/src/index.dox @@ -1,11 +1,11 @@ /** -\mainpage Rapida Manual +\mainpage Manual Web framework written in C and C++. -Table of contents: -1. \subpage get_started -2. \subpage development +[TOC] +- \subpage get_started +- \subpage development */ diff --git a/examples/c/example.c b/examples/c/example.c index e071506..b3a2089 100644 --- a/examples/c/example.c +++ b/examples/c/example.c @@ -1,5 +1,5 @@ #include "../../include/rapida.h" -#include "../../include/servers/fcgi.h" +#include "../../include/servers/tcp.h" #include #include #include @@ -52,6 +52,5 @@ int main() rpd_app_add_route(&app, "/products/:category/:id", &products_handler, NULL); - return rpd_fcgi_server_start(&app, "/tmp/webapp.socket"); - return 0; + return rpd_tcp_server_start(&app, "http://localhost:8080"); } diff --git a/examples/c/minimal.c b/examples/c/minimal.c index 536292b..ec4583a 100644 --- a/examples/c/minimal.c +++ b/examples/c/minimal.c @@ -1,8 +1,6 @@ #include "../../include/rapida.h" -#include "../../include/servers/fcgi.h" +#include "../../include/servers/tcp.h" #include /* for strdup() */ -#include - /* * \brief Process home page request. @@ -16,7 +14,7 @@ static void home_page_handler(rpd_req *req, rpd_res *res, void *userdata) { /* Check request method */ switch (req->method) { - case GET: + case HEAD: /* Process GET request */ res->status = rpd_res_st_ok; @@ -25,6 +23,7 @@ static void home_page_handler(rpd_req *req, rpd_res *res, void *userdata) * Rapida will free it all. */ res->content_type = strdup("text/plain"); + case GET: res->body = strdup("Hello World!"); break; default: @@ -51,5 +50,5 @@ int main() rpd_app_add_route(&app, "/", &home_page_handler, NULL); /* Run the application and return its status code. */ - return rpd_fcgi_server_start(&app, "/tmp/webapp.socket"); + return rpd_tcp_server_start(&app, "http://localhost:8080"); } diff --git a/examples/cxx/example.cxx b/examples/cxx/example.cxx index 2742e9c..85480b3 100644 --- a/examples/cxx/example.cxx +++ b/examples/cxx/example.cxx @@ -1,5 +1,5 @@ #include "../../include/rapida.hxx" -#include "../../include/servers/fcgi.h" +#include "../../include/servers/tcp.h" #include class ProductRoute : public rpd::Route { @@ -49,5 +49,5 @@ int main() */ app.add_route("/products/:category/:id", new ProductRoute()); - return rpd_fcgi_server_start(app.c_app(), "/tmp/webapp.socket"); + return rpd_tcp_server_start(app.c_app(), "http://localhost:8080"); } diff --git a/examples/cxx/minimal.cxx b/examples/cxx/minimal.cxx index fa98c1b..d8febda 100644 --- a/examples/cxx/minimal.cxx +++ b/examples/cxx/minimal.cxx @@ -1,5 +1,5 @@ #include "../../include/rapida.hxx" -#include "../../include/servers/fcgi.h" +#include "../../include/servers/tcp.h" /* @@ -39,5 +39,5 @@ int main() app.add_route("/", new Home()); - return rpd_fcgi_server_start(app.c_app(), "/tmp/webapp.socket"); + return rpd_tcp_server_start(app.c_app(), "http://localhost:8080"); } diff --git a/include/App.hxx b/include/App.hxx index b31a63d..9a8655f 100644 --- a/include/App.hxx +++ b/include/App.hxx @@ -16,9 +16,8 @@ namespace rpd { class App { public: /*! - * Creates an rpd app and initializes FastCGI. + * Creates a Rapida application instance. * \brief Default constructor - * \param socket_path UNIX Socket path. */ App() { diff --git a/include/Response.hxx b/include/Response.hxx index 2b204a8..75db59a 100644 --- a/include/Response.hxx +++ b/include/Response.hxx @@ -114,7 +114,6 @@ public: * \brief Render data to HTML template. * \param path Path to HTML template relative to dist location. * \param data Template data to interpolate. - * \param out FastCGI output stream. */ void render(const char *path, nlohmann::json data); #endif diff --git a/include/app.h b/include/app.h index 7475f1c..3250767 100644 --- a/include/app.h +++ b/include/app.h @@ -35,7 +35,8 @@ int rpd_app_create(rpd_app *app); /*! * Handle accepted request. * \param app Application instance. - * \param req FastCGI request. + * \param req Request. + * \param res Response. */ void rpd_app_handle_request(rpd_app *app, rpd_req *req, rpd_res *res); diff --git a/include/response.h b/include/response.h index c567797..6e6d64e 100644 --- a/include/response.h +++ b/include/response.h @@ -93,13 +93,22 @@ typedef struct { } rpd_res; /*! - * \brief Initialize response data from FastCGI request. + * \brief Initialize response data. * * \param dest Response instance. - * \param req FastCGI request. */ void rpd_res_init(rpd_res *dest); +/*! + * \brief Write response headers to string buffer. + * + * \param dest Destination buffer. + * \param src Response. + * + * \return Status code. 0 is success. + */ +int rpd_res_headers_str(char **dest, const rpd_res *src); + /*! * \brief Write response to string buffer. * diff --git a/include/servers/tcp.h b/include/servers/tcp.h new file mode 100644 index 0000000..0ed2a28 --- /dev/null +++ b/include/servers/tcp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* Copyright 2022 Ivan Polyakov */ + +/*! + * \file tcp.h + * \brief Rapida TCP server + */ +#ifndef RAPIDA_SERVERS_TCP_H_ENTRY +#define RAPIDA_SERVERS_TCP_H_ENTRY + +#include "../app.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief Starts Rapida TCP server. + * \param app Application instance. + * \param addr URL address to listen. + * + * \return Status. 0 is success. + */ +int rpd_tcp_server_start(rpd_app *app, const char *addr); + +#ifdef __cplusplus +} +#endif + +#endif /* RAPIDA_SERVERS_TCP_H_ENTRY */ diff --git a/servers/fcgi.c b/servers/fcgi.c index d02579a..1d3d335 100644 --- a/servers/fcgi.c +++ b/servers/fcgi.c @@ -1,3 +1,6 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* Copyright 2022 Ivan Polyakov */ + #include "../include/servers/fcgi.h" #include diff --git a/servers/tcp.c b/servers/tcp.c new file mode 100644 index 0000000..89e4df6 --- /dev/null +++ b/servers/tcp.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* Copyright 2022 Ivan Polyakov */ + +#include "servers/tcp.h" +#include "../c/utils.h" +#include +#include + +/* Handle interrupts, like Ctrl-C */ +static int s_signo; +static void signal_handler(int signo) +{ + s_signo = signo; +} + +static int mg_str_alloc(char **dest, const struct mg_str str) +{ + *dest = (char *) realloc(*dest, sizeof(char) * (str.len + 1)); + if (!*dest) { + perror("realloc"); + return 1; + } + memcpy(*dest, str.ptr, str.len); + (*dest)[str.len] = '\0'; + return 0; +} + +static int mg_to_rpd_req(rpd_req *req, struct mg_http_message *msg) +{ + char *tmp = NULL; + if (mg_str_alloc(&tmp, msg->method)) + return 1; + req->method = rpd_req_smethod(tmp); + + req->body = msg->body.len ? rpd_strdup(msg->body.ptr) : NULL; + + if (mg_str_alloc(&tmp, msg->uri)) + return 1; + rpd_url_parse(&req->path, tmp); + + rpd_keyval_init(&req->query, 0); + if (msg->query.len) { + if (mg_str_alloc(&tmp, msg->query)) + return 1; + rpd_query_parse(&req->query, tmp); + } + + free(tmp); + return 0; +} + +static void handle_request(struct mg_connection *conn, int ev, void *ev_data, void *app) +{ + if (ev == MG_EV_HTTP_MSG) { + rpd_req *req; + rpd_res *res; + char *headers_buff; + + req = (rpd_req *) malloc(sizeof(rpd_req)); + res = (rpd_res *) malloc(sizeof(rpd_res)); + + mg_to_rpd_req(req, (struct mg_http_message *) ev_data); + rpd_res_init(res); + + rpd_app_handle_request((rpd_app *) app, req, res); + rpd_res_headers_str(&headers_buff, res); + mg_http_reply(conn, res->status, headers_buff, res->body ? res->body : ""); + + free(headers_buff); + rpd_req_cleanup(req); + rpd_res_cleanup(res); + free(req); + free(res); + } +} + +int rpd_tcp_server_start(rpd_app *app, const char *addr) +{ + struct mg_mgr mgr; + struct mg_connection *c; + app->running = 1; + + /* setup signals handler */ + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + mg_mgr_init(&mgr); + + if ((c = mg_http_listen(&mgr, addr, handle_request, app)) == NULL) { + MG_ERROR(("Cannot listen on %s. Use http://ADDR:PORT or :PORT", addr)); + return EXIT_FAILURE; + } + MG_INFO(("Mongoose version : v%s", MG_VERSION)); + MG_INFO(("Rapida version : v%s", RPD_VERSION)); + MG_INFO(("Listening on : %s", addr)); + while (s_signo == 0 && app->running) + mg_mgr_poll(&mgr, 1000); + + app->running = 0; + MG_INFO(("Exiting on signal %d", s_signo)); + mg_mgr_free(&mgr); + return 0; +} From c579751ef62d97923289368293e2ff4dd5d2f5b7 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 31 Oct 2022 20:07:06 +0300 Subject: [PATCH 7/9] installing mongoose --- .drone.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index fc56f77..5ea177e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -14,7 +14,9 @@ steps: image: gcc:11-bullseye commands: - apt update -y - - apt install -y libfcgi-dev libfcgi-bin doxygen + - apt install -y libfcgi-dev libfcgi-bin doxygen git + - git clone https://github.com/cesanta/mongoose.git + - cd mongoose && make install && cd .. - make all DEBUG=1 - make docs @@ -58,6 +60,8 @@ steps: commands: - apt update -y - apt install -y libfcgi-dev libfcgi-bin doxygen + - git clone https://github.com/cesanta/mongoose.git + - cd mongoose && make install && cd .. - make all DEBUG=1 - make docs From 89a8c4760255622b32fe694c1123b7716d66b9aa Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 31 Oct 2022 20:12:52 +0300 Subject: [PATCH 8/9] installing git and deleting target dir --- .drone.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 5ea177e..c1214bf 100644 --- a/.drone.yml +++ b/.drone.yml @@ -40,6 +40,7 @@ steps: target: from_secret: deploy_docs_dev_target source: docs/dist/html/ + delete: true --- @@ -59,7 +60,7 @@ steps: image: gcc:11-bullseye commands: - apt update -y - - apt install -y libfcgi-dev libfcgi-bin doxygen + - apt install -y libfcgi-dev libfcgi-bin doxygen git - git clone https://github.com/cesanta/mongoose.git - cd mongoose && make install && cd .. - make all DEBUG=1 @@ -85,3 +86,4 @@ steps: target: from_secret: deploy_docs_target source: docs/dist/html/ + delete: true From eff7d7c3970eef5a17c4306a7ab9baa8d6062c80 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Mon, 31 Oct 2022 21:13:49 +0300 Subject: [PATCH 9/9] docs compilation with doxygen 1.9.1 fixed --- docs/src/get_started.dox | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/src/get_started.dox b/docs/src/get_started.dox index 24ac1f2..ba5df65 100644 --- a/docs/src/get_started.dox +++ b/docs/src/get_started.dox @@ -21,7 +21,6 @@ C example: C++ example: ------------ - \include minimal.cxx More examples you can find at http://git.vilor.one/rapida/rapida/examples @@ -48,7 +47,7 @@ to the library, but you can change this by setting the _make_ flags. For example, to disable FastCGI server, you need to pass `FCGI_SERVER=0` flag to `make` command like this: -```sh +``` make FCGI_SERVER=0 ```