From acc3e6a3ad0b6193286886015109839d642f1ef6 Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Tue, 12 Apr 2022 22:33:36 +0200 Subject: [PATCH 01/80] Cleanup files uploaded on request deletion (#266) * http_request: Remove uploaded files in destructor If the user needs those files, she should copy/move theme in the request handler. References: #264 Signed-off-by: Alexander Dahl * test: integ: file_upload: Remove redundant file delete Not needed anymore. http_request destructor does cleanup now. * test: integ: file_upload: Check uploaded files are deleted * test: integ: file_upload: Stop webserver earlier The webserver runs in a different thread than the test, therefor deleting the uploaded files and checking if they are deleted might lead into a race condition, and thus into tests failing sometimes, but not always. Moving the webserver stop and destructor behind the curl action should be safe, every information needed for the test is copied to or in the resource handler. --- src/http_request.cpp | 9 ++++++++ src/httpserver/http_request.hpp | 5 ++++ test/integ/file_upload.cpp | 41 ++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/http_request.cpp b/src/http_request.cpp index 3d88a382..195dddbc 100644 --- a/src/http_request.cpp +++ b/src/http_request.cpp @@ -256,4 +256,13 @@ std::ostream &operator<< (std::ostream &os, const http_request &r) { return os; } +http_request::~http_request() { + for ( const auto &file_key : this->get_files() ) { + for ( const auto &files : file_key.second ) { + // C++17 has std::filesystem::remove() + remove(files.second.get_file_system_file_name().c_str()); + } + } +} + } // namespace httpserver diff --git a/src/httpserver/http_request.hpp b/src/httpserver/http_request.hpp index 739de326..560f76c5 100644 --- a/src/httpserver/http_request.hpp +++ b/src/httpserver/http_request.hpp @@ -46,6 +46,8 @@ struct MHD_Connection; namespace httpserver { +namespace details { struct modded_request; } + /** * Class representing an abstraction for an Http Request. It is used from classes using these apis to receive information through http protocol. **/ @@ -254,6 +256,8 @@ class http_request { http_request& operator=(const http_request& b) = default; http_request& operator=(http_request&& b) = default; + ~http_request(); + std::string path; std::string method; std::map args; @@ -356,6 +360,7 @@ class http_request { const std::map get_headerlike_values(enum MHD_ValueKind kind) const; friend class webserver; + friend struct details::modded_request; }; std::ostream &operator<< (std::ostream &os, const http_request &r); diff --git a/test/integ/file_upload.cpp b/test/integ/file_upload.cpp index 00cbd9ab..ca506d97 100644 --- a/test/integ/file_upload.cpp +++ b/test/integ/file_upload.cpp @@ -59,6 +59,12 @@ static size_t TEST_CONTENT_SIZE_2 = 28; static const char* TEST_PARAM_KEY = "param_key"; static const char* TEST_PARAM_VALUE = "Value of test param"; +static bool file_exists(const string &path) { + struct stat sb; + + return (stat(path.c_str(), &sb) == 0); +} + static CURLcode send_file_to_webserver(bool add_second_file, bool append_parameters) { curl_global_init(CURL_GLOBAL_ALL); @@ -191,6 +197,9 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk) CURLcode res = send_file_to_webserver(false, false); LT_ASSERT_EQ(res, 0); + ws->stop(); + delete ws; + string actual_content = resource.get_content(); LT_CHECK_EQ(actual_content.find(FILENAME_IN_GET_CONTENT) != string::npos, true); LT_CHECK_EQ(actual_content.find(TEST_CONTENT) != string::npos, true); @@ -216,10 +225,7 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk) httpserver::http::http_utils::upload_filename_template; LT_CHECK_EQ(file->second.get_file_system_file_name().substr(0, file->second.get_file_system_file_name().size() - 6), expected_filename.substr(0, expected_filename.size() - 6)); - unlink(file->second.get_file_system_file_name().c_str()); - - ws->stop(); - delete ws; + LT_CHECK_EQ(file_exists(file->second.get_file_system_file_name()), false); LT_END_AUTO_TEST(file_upload_memory_and_disk) LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_via_put) @@ -271,6 +277,9 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_additional_par CURLcode res = send_file_to_webserver(false, true); LT_ASSERT_EQ(res, 0); + ws->stop(); + delete ws; + string actual_content = resource.get_content(); LT_CHECK_EQ(actual_content.find(FILENAME_IN_GET_CONTENT) != string::npos, true); LT_CHECK_EQ(actual_content.find(TEST_CONTENT) != string::npos, true); @@ -301,10 +310,7 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_additional_par httpserver::http::http_utils::upload_filename_template; LT_CHECK_EQ(file->second.get_file_system_file_name().substr(0, file->second.get_file_system_file_name().size() - 6), expected_filename.substr(0, expected_filename.size() - 6)); - unlink(file->second.get_file_system_file_name().c_str()); - - ws->stop(); - delete ws; + LT_CHECK_EQ(file_exists(file->second.get_file_system_file_name()), false); LT_END_AUTO_TEST(file_upload_memory_and_disk_additional_params) LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_two_files) @@ -325,6 +331,9 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_two_files) CURLcode res = send_file_to_webserver(true, false); LT_ASSERT_EQ(res, 0); + ws->stop(); + delete ws; + string actual_content = resource.get_content(); LT_CHECK_EQ(actual_content.find(FILENAME_IN_GET_CONTENT) != string::npos, true); LT_CHECK_EQ(actual_content.find(TEST_CONTENT) != string::npos, true); @@ -355,7 +364,7 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_two_files) httpserver::http::http_utils::upload_filename_template; LT_CHECK_EQ(file->second.get_file_system_file_name().substr(0, file->second.get_file_system_file_name().size() - 6), expected_filename.substr(0, expected_filename.size() - 6)); - unlink(file->second.get_file_system_file_name().c_str()); + LT_CHECK_EQ(file_exists(file->second.get_file_system_file_name()), false); file_key++; LT_CHECK_EQ(file_key->first, TEST_KEY_2); @@ -370,11 +379,7 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_and_disk_two_files) httpserver::http::http_utils::upload_filename_template; LT_CHECK_EQ(file->second.get_file_system_file_name().substr(0, file->second.get_file_system_file_name().size() - 6), expected_filename.substr(0, expected_filename.size() - 6)); - unlink(file->second.get_file_system_file_name().c_str()); - - - ws->stop(); - delete ws; + LT_CHECK_EQ(file_exists(file->second.get_file_system_file_name()), false); LT_END_AUTO_TEST(file_upload_memory_and_disk_two_files) LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_disk_only) @@ -395,6 +400,9 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_disk_only) CURLcode res = send_file_to_webserver(false, false); LT_ASSERT_EQ(res, 0); + ws->stop(); + delete ws; + string actual_content = resource.get_content(); LT_CHECK_EQ(actual_content.size(), 0); @@ -416,10 +424,7 @@ LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_disk_only) httpserver::http::http_utils::upload_filename_template; LT_CHECK_EQ(file->second.get_file_system_file_name().substr(0, file->second.get_file_system_file_name().size() - 6), expected_filename.substr(0, expected_filename.size() - 6)); - unlink(file->second.get_file_system_file_name().c_str()); - - ws->stop(); - delete ws; + LT_CHECK_EQ(file_exists(file->second.get_file_system_file_name()), false); LT_END_AUTO_TEST(file_upload_disk_only) LT_BEGIN_AUTO_TEST(file_upload_suite, file_upload_memory_only_incl_content) From bbdf033be9f06e3120143442b771b7a1231bb42e Mon Sep 17 00:00:00 2001 From: Ilya Brin <464157+ilyabrin@users.noreply.github.com> Date: Sun, 14 Aug 2022 03:18:40 +0300 Subject: [PATCH 02/80] Update README.md (#277) fixed little typos and syntax highlighting has been added --- README.md | 65 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 07021ed9..2b662f27 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Here are listed the libhttpserver specific options (the canonical configure opti ## Getting Started The most basic example of creating a server and handling a requests for the path `/hello`: - +```cpp #include using namespace httpserver; @@ -141,7 +141,7 @@ The most basic example of creating a server and handling a requests for the path return 0; } - +``` To test the above example, you could run the following command from a terminal: curl -XGET -v http://localhost:8080/hello @@ -166,9 +166,9 @@ You can also check this example on [github](https://github.com/etr/libhttpserver ## Create and work with a webserver As you can see from the example above, creating a webserver with standard configuration is quite simple: - +```cpp webserver ws = create_webserver(8080); - +``` The `create_webserver` class is a supporting _builder_ class that eases the building of a webserver through chained syntax. ### Basic Startup Options @@ -214,6 +214,7 @@ In all these 3 cases libhttpserver would provide a standard HTTP response to the * _.internal_error_resource(**const shared_ptr(*render_ptr)(const http_request&)** resource):_ Specifies a function to handle a request that is causing an uncaught exception during its execution. **REMEMBER:** is this callback is causing an exception itself, the standard default response from libhttpserver will be reported to the HTTP client. #### Example of custom errors: +```cpp #include using namespace httpserver; @@ -246,7 +247,7 @@ In all these 3 cases libhttpserver would provide a standard HTTP response to the return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v http://localhost:8080/hello @@ -262,6 +263,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver * _.log_error(**void(*log_error_ptr)(const std::string&)** functor):_ Specifies a function used to log errors generating from the server. #### Example of custom logging callback +```cpp #include #include @@ -288,7 +290,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v http://localhost:8080/hello @@ -312,6 +314,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver * _.https_priorities(**const std::string&** priority_string):_ SSL/TLS protocol version and ciphers. Must be followed by a string specifying the SSL/TLS protocol versions and ciphers that are acceptable for the application. The string is passed unchanged to gnutls_priority_init. If this option is not specified, `"NORMAL"` is used. #### Minimal example using HTTPS +```cpp #include using namespace httpserver; @@ -335,7 +338,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v -k 'https://localhost:8080/hello' @@ -355,10 +358,10 @@ You should calculate the value of NC_SIZE based on the number of connections per * _.digest_auth_random(**const std::string&** nonce_seed):_ Digest Authentication nonce’s seed. For security, you SHOULD provide a fresh random nonce when actually using Digest Authentication with libhttpserver in production. ### Examples of chaining syntax to create a webserver - +```cpp webserver ws = create_webserver(8080) - .no_ssl() - .no_ipv6() + .no_ssl() + .no_ipv6() .no_debug() .no_pedantic() .no_basic_auth() @@ -367,12 +370,14 @@ You should calculate the value of NC_SIZE based on the number of connections per .no_regex_checking() .no_ban_system() .no_post_process(); +``` ## +```cpp webserver ws = create_webserver(8080) .use_ssl() .https_mem_key("key.pem") .https_mem_cert("cert.pem"); - +``` ### Starting and stopping a webserver Once a webserver is created, you can manage its execution through the following methods on the `webserver` class: * _**void** webserver::start(**bool** blocking):_ Allows to start a server. If the `blocking` flag is passed as `true`, it will block the execution of the current thread until a call to stop on the same webserver object is performed. @@ -397,6 +402,7 @@ Given this, the `http_resource` class contains the following extensible methods * _**const std::shared_ptr** http_resource::render(**const http_request&** req):_ Invoked as a backup method if the matching method is not implemented. It can be used whenever you want all the invocations on a URL to activate the same behavior regardless of the HTTP method requested. The default implementation of the `render` method returns an empty response with a `404`. #### Example of implementation of render methods +```cpp #include using namespace httpserver; @@ -421,7 +427,7 @@ Given this, the `http_resource` class contains the following extensible methods return 0; } - +``` To test the above example, you can run the following commands from a terminal: * `curl -XGET -v http://localhost:8080/hello`: will return `GET: Hello, World!`. * `curl -XPOST -v http://localhost:8080/hello`: will return `OTHER: Hello, World!`. You can try requesting other methods beside `POST` to verify how the same message will be returned. @@ -436,6 +442,7 @@ The base `http_resource` class has a set of methods that can be used to allow an * _**void** http_resource::disallow_all():_ Marks all HTTP methods as not allowed. #### Example of methods allowed/disallowed +```cpp #include using namespace httpserver; @@ -458,7 +465,7 @@ The base `http_resource` class has a set of methods that can be used to allow an return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v http://localhost:8080/hello @@ -482,7 +489,7 @@ There are essentially four ways to specify an endpoint string: * **A parametrized path. (e.g. `"/path/to/resource/with/{arg1}/{arg2}/in/url"`)**. In this case, the webserver will match the argument with any value passed. In addition to this, the arguments will be passed to the resource as part of the arguments (readable from the `http_request::get_arg` method - see [here](#parsing-requests)). For example, if passing `"/path/to/resource/with/{arg1}/{arg2}/in/url"` will match any request on URL with any value in place of `{arg1}` and `{arg2}`. * **A parametrized path with custom parameters.** This is the same of a normal parametrized path, but allows to specify a regular expression for the argument (e.g. `"/path/to/resource/with/{arg1|[0-9]+}/{arg2|[a-z]+}/in/url"`. In this case, the webserver will match the arguments with any value passed that satisfies the regex. In addition to this, as above, the arguments will be passed to the resource as part of the arguments (readable from the `http_request::get_arg` method - see [here](#parsing-requests)). For example, if passing `"/path/to/resource/with/{arg1|[0-9]+}/{arg2|[a-z]+}/in/url"` will match requests on URLs like `"/path/to/resource/with/10/AA/in/url"` but not like `""/path/to/resource/with/BB/10/in/url""` * Any of the above marked as `family`. Will match any request on URLs having path that is prefixed by the path passed. For example, if family is set to `true` and endpoint is set to `"/path"`, the webserver will route to the resource not only the requests against `"/path"` but also everything in its nested path `"/path/on/the/previous/one"`. - +```cpp #include using namespace httpserver; @@ -526,7 +533,7 @@ There are essentially four ways to specify an endpoint string: return 0; } - +``` To test the above example, you can run the following commands from a terminal: * `curl -XGET -v http://localhost:8080/hello`: will return the `Hello, World!` message. @@ -582,6 +589,7 @@ Details on the `http::file_info` structure. * _**const std::string** get_transfer_encoding() **const**:_ Returns the transfer encoding of the file uploaded through the HTTP request. #### Example of handler reading arguments from a request +```cpp #include using namespace httpserver; @@ -602,7 +610,7 @@ Details on the `http::file_info` structure. return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v "http://localhost:8080/hello?name=John" @@ -634,6 +642,7 @@ The `http_response` class offers an additional set of methods to "decorate" your * _**void** shoutCAST():_ Mark the response as a `shoutCAST` one. ### Example of response setting headers +```cpp #include using namespace httpserver; @@ -656,7 +665,7 @@ The `http_response` class offers an additional set of methods to "decorate" your return 0; } - +``` To test the above example, you could run the following command from a terminal: curl -XGET -v "http://localhost:8080/hello" @@ -691,6 +700,7 @@ Examples of valid IPs include: * `"::ffff:192.0.*.*"`: ranges of IPV4 IPs nested into IPV6. #### Example of IP Whitelisting/Blacklisting +```cpp #include using namespace httpserver; @@ -714,7 +724,7 @@ Examples of valid IPs include: return 0; } - +``` To test the above example, you could run the following command from a terminal: curl -XGET -v "http://localhost:8080/hello" @@ -733,6 +743,7 @@ Digest authentication uses a one-way authentication method based on MD5 hash alg Client certificate authentication uses a X.509 certificate from the client. This is the strongest authentication mechanism but it requires the use of HTTPS. Client certificate authentication can be used simultaneously with Basic or Digest Authentication in order to provide a two levels authentication (like for instance separate machine and user authentication). You can enable/disable support for Certificate authentication through the `use_ssl` and `no_ssl` methods of the `create_webserver` class. ### Using Basic Authentication +```cpp #include using namespace httpserver; @@ -756,7 +767,7 @@ Client certificate authentication uses a X.509 certificate from the client. This return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v -u myuser:mypass "http://localhost:8080/hello" @@ -766,6 +777,7 @@ You will receive back the user and password you passed in input. Try to pass the You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/basic_authentication.cpp). ### Using Digest Authentication +```cpp #include #define MY_OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" @@ -797,25 +809,26 @@ You can also check this example on [github](https://github.com/etr/libhttpserver return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v --digest --user myuser:mypass localhost:8080/hello -You will receive a `SUCCESS` in response (observe the response message from the server in detail and you'll see the full interaction). Try to pass the wrong credentials or send a request without `digest` active to see the failure. +You will receive a `SUCCESS` in response (observe the response message from the server in detail and you'll see the full interaction). Try to pass the wrong credentials or send a request without `digest` active to see the failure. You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/digest_authentication.cpp). [Back to TOC](#table-of-contents) ## HTTP Utils -libhttpserver provides a set of constants to help you develop your HTTP server. It would be redudant to list them here; so, please, consult the list directly [here](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp). +libhttpserver provides a set of constants to help you develop your HTTP server. It would be redundant to list them here; so, please, consult the list directly [here](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp). [Back to TOC](#table-of-contents) ## Other Examples #### Example of returning a response from a file +```cpp #include using namespace httpserver; @@ -836,7 +849,7 @@ libhttpserver provides a set of constants to help you develop your HTTP server. return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v localhost:8080/hello @@ -844,6 +857,7 @@ To test the above example, you can run the following command from a terminal: You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/minimal_file_response.cpp). #### Example of a deferred response through callback +```cpp #include using namespace httpserver; @@ -878,7 +892,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v localhost:8080/hello @@ -886,6 +900,7 @@ To test the above example, you can run the following command from a terminal: You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/minimal_deferred.cpp). #### Example of a deferred response through callback (passing additional data along) +```cpp #include #include @@ -935,7 +950,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver return 0; } - +``` To test the above example, you can run the following command from a terminal: curl -XGET -v localhost:8080/hello From 415e02f01fb8cb97c91d6a615479531bae279b7c Mon Sep 17 00:00:00 2001 From: Jim Phillips Date: Thu, 1 Sep 2022 12:42:05 -0500 Subject: [PATCH 03/80] Fix unban_ip doc (#279) For use when default policy is ACCEPT, not REJECT. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b662f27..df7429f4 100644 --- a/README.md +++ b/README.md @@ -684,7 +684,7 @@ The system supports both IPV4 and IPV6 and manages them transparently. The only You can explicitly ban or allow an IP address using the following methods on the `webserver` class: * _**void** ban_ip(**const std::string&** ip):_ Adds one IP (or a range of IPs) to the list of the banned ones. Takes in input a `string` that contains the IP (or range of IPs) to ban. To use when the `default_policy` is `ACCEPT`. * _**void** allow_ip(**const std::string&** ip):_ Adds one IP (or a range of IPs) to the list of the allowed ones. Takes in input a `string` that contains the IP (or range of IPs) to allow. To use when the `default_policy` is `REJECT`. -* _**void** unban_ip(**const std::string&** ip):_ Removes one IP (or a range of IPs) from the list of the banned ones. Takes in input a `string` that contains the IP (or range of IPs) to remove from the list. To use when the `default_policy` is `REJECT`. +* _**void** unban_ip(**const std::string&** ip):_ Removes one IP (or a range of IPs) from the list of the banned ones. Takes in input a `string` that contains the IP (or range of IPs) to remove from the list. To use when the `default_policy` is `ACCEPT`. * _**void** disallow_ip(**const std::string&** ip):_ Removes one IP (or a range of IPs) from the list of the allowed ones. Takes in input a `string` that contains the IP (or range of IPs) to remove from the list. To use when the `default_policy` is `REJECT`. ### IP String Format From 8ab27253c8d61cf665457870ec75db1e61ce11e8 Mon Sep 17 00:00:00 2001 From: stuart-byma <113421362+stuart-byma@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:28:41 +0200 Subject: [PATCH 04/80] switch callback function pointers to std::function types (#283) --- src/httpserver/create_webserver.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/httpserver/create_webserver.hpp b/src/httpserver/create_webserver.hpp index 99369f60..d1503399 100644 --- a/src/httpserver/create_webserver.hpp +++ b/src/httpserver/create_webserver.hpp @@ -27,6 +27,7 @@ #include #include +#include #include #include "httpserver/http_response.hpp" @@ -40,10 +41,10 @@ namespace httpserver { class webserver; class http_request; -typedef const std::shared_ptr(*render_ptr)(const http_request&); -typedef bool(*validator_ptr)(const std::string&); -typedef void(*log_access_ptr)(const std::string&); -typedef void(*log_error_ptr)(const std::string&); +typedef std::function(const http_request&)> render_ptr; +typedef std::function validator_ptr; +typedef std::function log_access_ptr; +typedef std::function log_error_ptr; class create_webserver { public: From f33553c26bc59c6123383d57c07058cbaa7bc899 Mon Sep 17 00:00:00 2001 From: stuart-byma <113421362+stuart-byma@users.noreply.github.com> Date: Fri, 30 Sep 2022 21:51:33 +0200 Subject: [PATCH 05/80] Remove ineffective/unneeded const from shared_ptr return types (#285) * remove ineffective/unneeded const qualifier on shared_ptr return types * remove ineffective/unneeded const from shared_ptr instances in tests * revert accidental removal of const on pass by reference shared_ptrs --- README.md | 58 ++++++++++----------- examples/allowing_disallowing_methods.cpp | 2 +- examples/basic_authentication.cpp | 2 +- examples/benchmark_nodelay.cpp | 2 +- examples/benchmark_select.cpp | 2 +- examples/benchmark_threads.cpp | 2 +- examples/custom_access_log.cpp | 2 +- examples/custom_error.cpp | 6 +-- examples/deferred_with_accumulator.cpp | 2 +- examples/digest_authentication.cpp | 2 +- examples/file_upload.cpp | 4 +- examples/handlers.cpp | 4 +- examples/hello_with_get_arg.cpp | 2 +- examples/hello_world.cpp | 4 +- examples/minimal_deferred.cpp | 2 +- examples/minimal_file_response.cpp | 2 +- examples/minimal_hello_world.cpp | 2 +- examples/minimal_https.cpp | 2 +- examples/minimal_ip_ban.cpp | 2 +- examples/service.cpp | 32 ++++++------ examples/setting_headers.cpp | 2 +- examples/url_registration.cpp | 6 +-- src/httpserver/create_webserver.hpp | 2 +- src/httpserver/details/modded_request.hpp | 2 +- src/httpserver/http_resource.hpp | 20 ++++---- src/httpserver/webserver.hpp | 6 +-- src/webserver.cpp | 6 +-- test/integ/authentication.cpp | 4 +- test/integ/ban_system.cpp | 2 +- test/integ/basic.cpp | 62 +++++++++++------------ test/integ/deferred.cpp | 4 +- test/integ/file_upload.cpp | 4 +- test/integ/nodelay.cpp | 2 +- test/integ/threaded.cpp | 2 +- test/integ/ws_start_stop.cpp | 6 +-- test/unit/http_resource_test.cpp | 2 +- 36 files changed, 134 insertions(+), 134 deletions(-) diff --git a/README.md b/README.md index df7429f4..ca1ac442 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ The most basic example of creating a server and handling a requests for the path class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -219,17 +219,17 @@ In all these 3 cases libhttpserver would provide a standard HTTP response to the using namespace httpserver; - const std::shared_ptr not_found_custom(const http_request& req) { + std::shared_ptr not_found_custom(const http_request& req) { return std::shared_ptr(new string_response("Not found custom", 404, "text/plain")); } - const std::shared_ptr not_allowed_custom(const http_request& req) { + std::shared_ptr not_allowed_custom(const http_request& req) { return std::shared_ptr(new string_response("Not allowed custom", 405, "text/plain")); } class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -275,7 +275,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -321,7 +321,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -391,15 +391,15 @@ Once a webserver is created, you can manage its execution through the following The `http_resource` class represents a logical collection of HTTP methods that will be associated to a URL when registered on the webserver. The class is **designed for extension** and it is where most of your code should ideally live. When the webserver matches a request against a resource (see: [resource registration](#registering-resources)), the method correspondent to the one in the request (GET, POST, etc..) (see below) is called on the resource. Given this, the `http_resource` class contains the following extensible methods (also called `handlers` or `render methods`): -* _**const std::shared_ptr** http_resource::render_GET(**const http_request&** req):_ Invoked on an HTTP GET request. -* _**const std::shared_ptr** http_resource::render_POST(**const http_request&** req):_ Invoked on an HTTP POST request. -* _**const std::shared_ptr** http_resource::render_PUT(**const http_request&** req):_ Invoked on an HTTP PUT request. -* _**const std::shared_ptr** http_resource::render_HEAD(**const http_request&** req):_ Invoked on an HTTP HEAD request. -* _**const std::shared_ptr** http_resource::render_DELETE(**const http_request&** req):_ Invoked on an HTTP DELETE request. -* _**const std::shared_ptr** http_resource::render_TRACE(**const http_request&** req):_ Invoked on an HTTP TRACE request. -* _**const std::shared_ptr** http_resource::render_OPTIONS(**const http_request&** req):_ Invoked on an HTTP OPTIONS request. -* _**const std::shared_ptr** http_resource::render_CONNECT(**const http_request&** req):_ Invoked on an HTTP CONNECT request. -* _**const std::shared_ptr** http_resource::render(**const http_request&** req):_ Invoked as a backup method if the matching method is not implemented. It can be used whenever you want all the invocations on a URL to activate the same behavior regardless of the HTTP method requested. The default implementation of the `render` method returns an empty response with a `404`. +* _**std::shared_ptr** http_resource::render_GET(**const http_request&** req):_ Invoked on an HTTP GET request. +* _**std::shared_ptr** http_resource::render_POST(**const http_request&** req):_ Invoked on an HTTP POST request. +* _**std::shared_ptr** http_resource::render_PUT(**const http_request&** req):_ Invoked on an HTTP PUT request. +* _**std::shared_ptr** http_resource::render_HEAD(**const http_request&** req):_ Invoked on an HTTP HEAD request. +* _**std::shared_ptr** http_resource::render_DELETE(**const http_request&** req):_ Invoked on an HTTP DELETE request. +* _**std::shared_ptr** http_resource::render_TRACE(**const http_request&** req):_ Invoked on an HTTP TRACE request. +* _**std::shared_ptr** http_resource::render_OPTIONS(**const http_request&** req):_ Invoked on an HTTP OPTIONS request. +* _**std::shared_ptr** http_resource::render_CONNECT(**const http_request&** req):_ Invoked on an HTTP CONNECT request. +* _**std::shared_ptr** http_resource::render(**const http_request&** req):_ Invoked as a backup method if the matching method is not implemented. It can be used whenever you want all the invocations on a URL to activate the same behavior regardless of the HTTP method requested. The default implementation of the `render` method returns an empty response with a `404`. #### Example of implementation of render methods ```cpp @@ -409,11 +409,11 @@ Given this, the `http_resource` class contains the following extensible methods class hello_world_resource : public http_resource { public: - const std::shared_ptr render_GET(const http_request&) { + std::shared_ptr render_GET(const http_request&) { return std::shared_ptr(new string_response("GET: Hello, World!")); } - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("OTHER: Hello, World!")); } }; @@ -449,7 +449,7 @@ The base `http_resource` class has a set of methods that can be used to allow an class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -496,21 +496,21 @@ There are essentially four ways to specify an endpoint string: class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; class handling_multiple_resource : public http_resource { public: - const std::shared_ptr render(const http_request& req) { + std::shared_ptr render(const http_request& req) { return std::shared_ptr(new string_response("Your URL: " + req.get_path())); } }; class url_args_resource : public http_resource { public: - const std::shared_ptr render(const http_request& req) { + std::shared_ptr render(const http_request& req) { return std::shared_ptr(new string_response("ARGS: " + req.get_arg("arg1") + " and " + req.get_arg("arg2"))); } }; @@ -596,7 +596,7 @@ Details on the `http::file_info` structure. class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request& req) { + std::shared_ptr render(const http_request& req) { return std::shared_ptr(new string_response("Hello: " + req.get_arg("name"))); } }; @@ -649,7 +649,7 @@ The `http_response` class offers an additional set of methods to "decorate" your class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { std::shared_ptr response = std::shared_ptr(new string_response("Hello, World!")); response->with_header("MyHeader", "MyValue"); return response; @@ -707,7 +707,7 @@ Examples of valid IPs include: class hello_world_resource : public http_resource { public: - const std::shared_ptr render(const http_request&) { + std::shared_ptr render(const http_request&) { return std::shared_ptr(new string_response("Hello, World!")); } }; @@ -750,7 +750,7 @@ Client certificate authentication uses a X.509 certificate from the client. This class user_pass_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const http_request& req) { + std::shared_ptr render_GET(const http_request& req) { if (req.get_user() != "myuser" || req.get_pass() != "mypass") { return std::shared_ptr(new basic_auth_fail_response("FAIL", "test@example.com")); } @@ -786,7 +786,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver class digest_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const http_request& req) { + std::shared_ptr render_GET(const http_request& req) { if (req.get_digested_user() == "") { return std::shared_ptr(new digest_auth_fail_response("FAIL", "test@example.com", MY_OPAQUE, true)); } @@ -835,7 +835,7 @@ libhttpserver provides a set of constants to help you develop your HTTP server. class file_response_resource : public http_resource { public: - const std::shared_ptr render_GET(const http_request& req) { + std::shared_ptr render_GET(const http_request& req) { return std::shared_ptr(new file_response("test_content", 200, "text/plain")); } }; @@ -878,7 +878,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver class deferred_resource : public http_resource { public: - const std::shared_ptr render_GET(const http_request& req) { + std::shared_ptr render_GET(const http_request& req) { return std::shared_ptr >(new deferred_response(test_callback, nullptr, "cycle callback response")); } }; @@ -935,7 +935,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver class deferred_resource : public http_resource { public: - const std::shared_ptr render_GET(const http_request& req) { + std::shared_ptr render_GET(const http_request& req) { std::shared_ptr > closure_data(new std::atomic(counter++)); return std::shared_ptr > >(new deferred_response >(test_callback, closure_data, "cycle callback response")); } diff --git a/examples/allowing_disallowing_methods.cpp b/examples/allowing_disallowing_methods.cpp index a0578f5e..73389142 100644 --- a/examples/allowing_disallowing_methods.cpp +++ b/examples/allowing_disallowing_methods.cpp @@ -22,7 +22,7 @@ class hello_world_resource : public httpserver::http_resource { public: - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return std::shared_ptr(new httpserver::string_response("Hello, World!")); } }; diff --git a/examples/basic_authentication.cpp b/examples/basic_authentication.cpp index cc90f55b..2661806f 100644 --- a/examples/basic_authentication.cpp +++ b/examples/basic_authentication.cpp @@ -22,7 +22,7 @@ class user_pass_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const httpserver::http_request& req) { + std::shared_ptr render_GET(const httpserver::http_request& req) { if (req.get_user() != "myuser" || req.get_pass() != "mypass") { return std::shared_ptr(new httpserver::basic_auth_fail_response("FAIL", "test@example.com")); } diff --git a/examples/benchmark_nodelay.cpp b/examples/benchmark_nodelay.cpp index c1a6c1e7..96c2f570 100755 --- a/examples/benchmark_nodelay.cpp +++ b/examples/benchmark_nodelay.cpp @@ -32,7 +32,7 @@ class hello_world_resource : public httpserver::http_resource { resp(resp) { } - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return resp; } diff --git a/examples/benchmark_select.cpp b/examples/benchmark_select.cpp index 1edc1c00..ef5cd089 100755 --- a/examples/benchmark_select.cpp +++ b/examples/benchmark_select.cpp @@ -32,7 +32,7 @@ class hello_world_resource : public httpserver::http_resource { resp(resp) { } - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return resp; } diff --git a/examples/benchmark_threads.cpp b/examples/benchmark_threads.cpp index 1afe4dfb..db376168 100755 --- a/examples/benchmark_threads.cpp +++ b/examples/benchmark_threads.cpp @@ -32,7 +32,7 @@ class hello_world_resource : public httpserver::http_resource { resp(resp) { } - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return resp; } diff --git a/examples/custom_access_log.cpp b/examples/custom_access_log.cpp index dd2e4aa8..f1a59d53 100644 --- a/examples/custom_access_log.cpp +++ b/examples/custom_access_log.cpp @@ -28,7 +28,7 @@ void custom_access_log(const std::string& url) { class hello_world_resource : public httpserver::http_resource { public: - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return std::shared_ptr(new httpserver::string_response("Hello, World!")); } }; diff --git a/examples/custom_error.cpp b/examples/custom_error.cpp index 8e720835..a82d5972 100644 --- a/examples/custom_error.cpp +++ b/examples/custom_error.cpp @@ -20,17 +20,17 @@ #include -const std::shared_ptr not_found_custom(const httpserver::http_request&) { +std::shared_ptr not_found_custom(const httpserver::http_request&) { return std::shared_ptr(new httpserver::string_response("Not found custom", 404, "text/plain")); } -const std::shared_ptr not_allowed_custom(const httpserver::http_request&) { +std::shared_ptr not_allowed_custom(const httpserver::http_request&) { return std::shared_ptr(new httpserver::string_response("Not allowed custom", 405, "text/plain")); } class hello_world_resource : public httpserver::http_resource { public: - const std::shared_ptr render(const httpserver::http_request&) { + std::shared_ptr render(const httpserver::http_request&) { return std::shared_ptr(new httpserver::string_response("Hello, World!")); } }; diff --git a/examples/deferred_with_accumulator.cpp b/examples/deferred_with_accumulator.cpp index a55e4cd8..5e60f3e7 100644 --- a/examples/deferred_with_accumulator.cpp +++ b/examples/deferred_with_accumulator.cpp @@ -56,7 +56,7 @@ ssize_t test_callback(std::shared_ptr > closure_data, char* buf class deferred_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const httpserver::http_request&) { + std::shared_ptr render_GET(const httpserver::http_request&) { std::shared_ptr > closure_data(new std::atomic(counter++)); return std::shared_ptr > >(new httpserver::deferred_response >(test_callback, closure_data, "cycle callback response")); } diff --git a/examples/digest_authentication.cpp b/examples/digest_authentication.cpp index c919cf0e..40767dc2 100644 --- a/examples/digest_authentication.cpp +++ b/examples/digest_authentication.cpp @@ -24,7 +24,7 @@ class digest_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const httpserver::http_request& req) { + std::shared_ptr render_GET(const httpserver::http_request& req) { if (req.get_digested_user() == "") { return std::shared_ptr(new httpserver::digest_auth_fail_response("FAIL", "test@example.com", MY_OPAQUE, true)); } else { diff --git a/examples/file_upload.cpp b/examples/file_upload.cpp index 2c82e2a5..7e1afd5a 100644 --- a/examples/file_upload.cpp +++ b/examples/file_upload.cpp @@ -23,7 +23,7 @@ class file_upload_resource : public httpserver::http_resource { public: - const std::shared_ptr render_GET(const httpserver::http_request&) { + std::shared_ptr render_GET(const httpserver::http_request&) { std::string get_response = "\n"; get_response += " \n"; get_response += "
\n"; @@ -40,7 +40,7 @@ class file_upload_resource : public httpserver::http_resource { return std::shared_ptr(new httpserver::string_response(get_response, 200, "text/html")); } - const std::shared_ptr render_POST(const httpserver::http_request& req) { + std::shared_ptr render_POST(const httpserver::http_request& req) { std::string post_response = "\n"; post_response += "\n"; post_response += "