A very simple, fast, multithreaded, platform independent HTTP and HTTPS server and client library implemented using C++11 and Boost.Asio.

This project has moved to https://gitlab.com/eidheim/Simple-Web-Server.

Simple-Web-Server

A very simple, fast, multithreaded, platform independent HTTP and HTTPS server and client library implemented using C++11 and Asio (both Boost.Asio and standalone Asio can be used). Created to be an easy way to make REST resources available from C++ applications.

See https://gitlab.com/eidheim/Simple-WebSocket-Server for an easy way to make WebSocket/WebSocket Secure endpoints in C++. Also, feel free to check out the new C++ IDE supporting C++11/14/17: https://gitlab.com/cppit/jucipp.

Features

  • Asynchronous request handling
  • Thread pool if needed
  • Platform independent
  • HTTPS support
  • HTTP persistent connection (for HTTP/1.1)
  • Client supports chunked transfer encoding
  • Timeouts, if any of Server::timeout_request and Server::timeout_content are >0 (default: Server::timeout_request=5 seconds, and Server::timeout_content=300 seconds)
  • Simple way to add REST resources using regex for path, and anonymous functions

Usage

See http_examples.cpp or https_examples.cpp for example usage.

See particularly the JSON-POST (using Boost.PropertyTree) and the GET /match/[number] examples, which are most relevant.

Dependencies

  • Boost.Asio or standalone Asio
  • Boost is required to compile the examples
  • For HTTPS: OpenSSL libraries

Compile and run

Compile with a C++11 compliant compiler:

mkdir build
cd build
cmake ..
make
cd ..

HTTP

Run the server and client examples: ./build/http_examples

Direct your favorite browser to for instance http://localhost:8080/

HTTPS

Before running the server, an RSA private key (server.key) and an SSL certificate (server.crt) must be created. Follow, for instance, the instructions given here (for a self-signed certificate): http://www.akadia.com/services/ssh_test_certificate.html

Run the server and client examples: ./build/https_examples

Direct your favorite browser to for instance https://localhost:8080/

Owner
Ole Christian Eidheim
Moved to GitLab: https://gitlab.com/eidheim
Ole Christian Eidheim
Comments
  • Added forced client certificate validation

    Added forced client certificate validation

    Hi,

    A few notes about this pull request. The added else block is very usefull for debuging any ssl issues. It should probably either come in a #ifdef block or a configurable "if". ssl_session_ctx_id could be randomized, although as far as I know there's no security issue at having a const this way. the SSL_CTX_set_session_id_context line enable SSL session caching. It is mandatory for client certification. Performance wise it sound wise to enable it even if not using client cert (so the long ssl handshake is skipped) your verify_file is then used to match the client certificate.

  • Stack corruption?

    Stack corruption?

    I've been experiencing stack and heap collisions with my software and I've narrowed it down to server_http.hpp. Running valgrind with the following parameters reports some extremely large stack usage on my software and explains why I am consistently crashing in the same spot.

    I decided to run the same check on the http_examples.cpp and found extremely high usage of the stack as well. By the way I want to thank you for creating this simple but yet elegant library, it was exactly what I was looking for to serve REST/HTML web services for my project.

    Lastly, I run your library on both OSX and Linux and the crash only occurs on Linux. I will have to install and run valgrind on OSX and see if the stack behavior is the same on apple.

    valgrind --log-file=valgrind.log --leak-check=full --track-origins=yes --show-reachable=yes ./http_examples

    ==3641== Memcheck, a memory error detector ==3641== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==3641== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info ==3641== Command: ./http_examples ==3641== Parent PID: 2733 ==3641== ==3641== Warning: client switching stacks? SP change: 0x7aed548 --> 0x4036f98 ==3641== to suppress, use: --max-stackframe=61564336 or greater ==3641== Warning: client switching stacks? SP change: 0x4036d98 --> 0x7aed550 ==3641== to suppress, use: --max-stackframe=61564856 or greater ==3641== Warning: client switching stacks? SP change: 0x7aed508 --> 0x4036da0 ==3641== to suppress, use: --max-stackframe=61564776 or greater ==3641== further instances of this message will not be shown. ==3641==

  • Porting to Android and iOS

    Porting to Android and iOS

    Thanks for providing this interesting library. I would like to use it for mobile plateforms. Before starting I have some questions.

    1. Asio comes in two flaviours 1. standalone without boost and second without boost. Is it possible to avoid boost completely?
    2. Are there any REST methods available in the library?

    Regards

  • Limiting size of accepted requests

    Limiting size of accepted requests

    Thanks for writing a very useful tool. It's save me a ton of time on a project I am working on.

    One question: is there a configuration to set a maximum size for HTTP requests that the server will attempt to process? For IoT-like REST servers the HTTP requests are normally quite small so we could limit the size accepted. For constrained devices, I am worried that it may be possible for an attacker to force an out-of-memory situation by sending a very large request.

  • Regression with stream passed in client.request; it fails on a deref of nullptr

    Regression with stream passed in client.request; it fails on a deref of nullptr

    Since 2f32a2b52ff5c07393a21362900652c5f9f4dc88, it's no longer possible to use a stream with client.request.

    Tested with MSVS 2013 (toolset v120) and boost v1.62.

    I hacked a bit one of your test by using a stringstream instead of a simple string. Then it's easy to reproduce the bug.

    diff --git a/tests/io_test.cpp b/tests/io_test.cpp
    index e8b1c5d..6d014fd 100644
    --- a/tests/io_test.cpp
    +++ b/tests/io_test.cpp
    @@ -1,7 +1,8 @@
    -#include "server_http.hpp"
    -#include "client_http.hpp"
    +#include "../server_http.hpp"
    +#include "../client_http.hpp"
    
     #include <cassert>
    +#include <iostream>
    
     using namespace std;
    
    @@ -42,7 +43,8 @@ int main() {
    
         {
             stringstream output;
    -        auto r=client.request("POST", "/string", "A string");
    +        stringstream ss("A string");
    +        auto r=client.request("POST", "/string", ss);
             output << r->content.rdbuf();
             assert(output.str()=="A string");
         }
    
    

    It fails on a this which is null.

    >	ConsoleApplication1.exe!boost::asio::basic_io_object<boost::asio::stream_socket_service<boost::asio::ip::tcp>,1>::get_service()  Line 210 + 0x3 bytes	C++
     	ConsoleApplication1.exe!boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >::async_write_some<boost::asio::const_buffers_1,boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::const_buffers_1,boost::asio::detail::transfer_all_t,boost::asio::detail::write_streambuf_handler<std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> > > >(const boost::asio::const_buffers_1 & buffers, boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::const_buffers_1,boost::asio::detail::transfer_all_t,boost::asio::detail::write_streambuf_handler<std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> > > && handler)  Line 732 + 0x1b bytes	C++
     	ConsoleApplication1.exe!boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::const_buffers_1,boost::asio::detail::transfer_all_t,boost::asio::detail::write_streambuf_handler<std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> > >::operator()(const boost::system::error_code & ec, unsigned int bytes_transferred, int start)  Line 336 + 0x7b bytes	C++
     	ConsoleApplication1.exe!boost::asio::async_write<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::const_buffers_1,boost::asio::detail::transfer_all_t,boost::asio::detail::write_streambuf_handler<std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> > >(boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> > & s, const boost::asio::const_buffers_1 & buffers, boost::asio::detail::transfer_all_t completion_condition, boost::asio::detail::write_streambuf_handler<std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> > && handler)  Line 598 + 0x4d bytes	C++
     	ConsoleApplication1.exe!boost::asio::async_write<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,std::allocator<char>,<lambda_63f912c45b0502cf50ae96e7f30352af> >(boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> > & s, boost::asio::basic_streambuf<std::allocator<char> > & b, SimpleWeb::ClientBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::request::__l18::<lambda_63f912c45b0502cf50ae96e7f30352af> && handler)  Line 755 + 0x78 bytes	C++
     	ConsoleApplication1.exe!SimpleWeb::ClientBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::request(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & request_type, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & path, std::basic_iostream<char,std::char_traits<char> > & content, const std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > > & header)  Line 148 + 0x4b bytes	C++
     	ConsoleApplication1.exe!main()  Line 53 + 0x84 bytes	C++
     	ConsoleApplication1.exe!__tmainCRTStartup()  Line 626 + 0x19 bytes	C
     	ConsoleApplication1.exe!mainCRTStartup()  Line 466	C
     	kernel32.dll!751562c4() 	
     	[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]	
     	ntdll.dll!777c0719() 	
     	ntdll.dll!777c06e4() 	
    
  • Issue/44/clean compile

    Issue/44/clean compile

    The code now compiles cleanly under OSX and Linux with Clang. There was a lot of long vs. size_t warnings that I solved with static_cast however it might be a better idea to use the correct type. I would also suggest at one point or another that member variables used by subclasses or aggregates are exposed through member functions instead.

  • v3.0 - breaking changes

    v3.0 - breaking changes

    It is time for a major version bump, and the planned breaking changes are as follows:

    • Critical change: Current Server::Request::path will be split into path and query_string. This means that for instance server.resource["^/info$"]["GET"] will match both GET /info HTTP/1.1 and GET /info?a=b HTTP/1.1 requests.
    • ~Callbacks's std::shared_ptr parameter types will be changed to std::shared_ptr& in order to avoid unnecessary std::shared_ptr copies.~
    • ~Client and Server public constructors will be replaced with static ::create functions that returns std::shared_ptr's. We will take advantage of std::enable_shared_from_this to simplify the code in some cases, especially the Client code will be cleaner. Additionally, this will take care that Server and Client objects stay alive until io_service tasks using them are finished.~ ~This change depends on if it is possible to use std::enable_shared_from_this in both ServerBase/ClientBase and derived classes.~
    • Server::send is moved to Server::Response::send
    • Deprecated functions will be removed

    Feedback is welcome!

    edit: callback's parameters need to be non-const references in order to allow shared_ptr moves. edit2: added clang-format file edit3: .clang-format file has been added to master edit4: added deprecation warning if query string is present in a resource's regex. edit5: decided against the deprecation warning if query string is present in a resource's regex to keep the code clean. edit6: Server::send is moved to Server::Response::send edit7: Callbacks's std::shared_ptr parameter types will stay as is due to no real added value, and a lot of lambda captures would become non-const making it harder for the compiler to optimise. edit8: the Server and Client constructors will be as before.

  • Please make context, coroutine an optional dependency

    Please make context, coroutine an optional dependency

    boost context and by extension coroutine on MSVC requires MASM to build. MASM only comes with Visual Studio 2005 which is far behind 2014 and difficult to obtain. If possible please detect context and coroutine, other wise fall back on just threads. If that is not possible a CMAKE option would be an acceptable alternative.

  • Increase QPS for persistent connection

    Increase QPS for persistent connection

    Tested your QPS seemed very low 17K QPS on persistent connection . I used ab - Apache Venchmark with switch -k , it uses HTTP 1.0 keep-alive , so I had to add support to your code . It went from 11k to 17K , but it's still way lower then my stack based on Boost.asio.

    As a side note , your Händlers know too much of HTTP response . I am not advocating you to change it overnight , but it would be nice to have something like boost proposed in its samples .

    You are welocome to visit my project where I utilize 50K QPS CRUD handlers . https://github.com/venediktov/vanilla-rtb

    If you look at CRUD directory you will see http restful handsets that currently do 50K QPS on 4 core 2.2 GHz AMD ubuntu Linux .

    Please let me know if you care about this issue , i don't insist you fix it , but I was looking at my performance lately and got to see your stack by accident .

    Cheers , Vladimir .

  • Some changes

    Some changes

    I really like this server. Only fast part in the description was not so true. regex killed it.

    I created a handwritten the http parser. (nearly 4x speedup with index.html callback) * You can test this as the parser is a function pointer, see the server_http constructor.

    • Created a vector based callback matcher without regex
    • I changed the default callback to one get and one post callback
    • alot more
  • How to force the server disconnect disconnecting a client after responding?

    How to force the server disconnect disconnecting a client after responding?

    It seems in HTTP/1.0 a connection was closed after a request was handled by the server.

    And even in HTTP/1.1 if Connection: close header is set the server could close it right after responding. How can I do it with this library?

    PS: Great stuff this library! Thanks.

  • Support multiple calls to Response::send

    Support multiple calls to Response::send

    Currently, successive calls to Response::send may queue data to be sent twice. For example, the following will send "foo.foo.foo.bar.bar.baz.", when it should only send "foo.bar.baz.":

    *response << "foo.";
    response->send();
    *response << "bar.";
    response->send();
    *response << "baz.";
    response->send();
    

    This pull request fixes the issue by taking a snapshot of the buffer before sending it. It also contains a unit test that fails with the old code but passes with the new. No other unit tests are broken by this code.

  • 【warning C4996】Why is there such a warning?

    【warning C4996】Why is there such a warning?

    warning C4996

    'boost::asio::basic_socket::cancel': By default, this function always fails with operation_not_supported when used on Windows XP, Windows Server 2003, or earlier. Consult documentation for details.

    test C:\lib\simplewebserver\client_http.hpp 129

  • HttpClient::request()

    HttpClient::request()

  • The Networking TS

    The Networking TS

Minimalistic socket library inspired by Asio/Boost Asio, implemented in 1 single header file

cz-spas czspas (Small Portable Asynchronous Sockets) is minimalistic socket library inspired by Asio/Boost Asio, implemented in 1 single header file.

Nov 30, 2022
HTTP and WebSocket built on Boost.Asio in C++11
HTTP and WebSocket built on Boost.Asio in C++11

HTTP and WebSocket built on Boost.Asio in C++11 Branch Linux/OSX Windows Coverage Documentation Matrix master develop Contents Introduction Appearance

Jan 4, 2023
Boost::ASIO low-level redis client (connector)

bredis Boost::ASIO low-level redis client (connector), github gitee Features header only zero-copy (currently only for received replies from Redis) lo

Dec 8, 2022
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Jan 3, 2023
Packio - An asynchronous msgpack-RPC and JSON-RPC library built on top of Boost.Asio.

Header-only | JSON-RPC | msgpack-RPC | asio | coroutines This library requires C++17 and is designed as an extension to boost.asio. It will let you bu

Dec 26, 2022
A C++ header-only HTTP/HTTPS server and client library
A C++ header-only HTTP/HTTPS server and client library

cpp-httplib A C++11 single-file header-only cross platform HTTP/HTTPS library. It's extremely easy to setup. Just include the httplib.h file in your c

Dec 31, 2022
Asynchronous gRPC with Boost.Asio executors

asio-grpc This library provides an implementation of boost::asio::execution_context that dispatches work to a grpc::CompletionQueue. Making it possibl

Dec 31, 2022
Tiny cross-platform HTTP / HTTPS client library in C.

naett /nɛt:/ Tiny HTTP client library in C. Wraps native HTTP client functionality on macOS, Windows, Linux, iOS and Android in a single, simple non-b

Nov 28, 2022
H2O - the optimized HTTP/1, HTTP/2, HTTP/3 server

H2O - an optimized HTTP server with support for HTTP/1.x, HTTP/2 and HTTP/3 (experimental) Copyright (c) 2014-2019 DeNA Co., Ltd., Kazuho Oku, Tatsuhi

Dec 30, 2022
Multithreaded client socket server

-------------------------------------------------------------------------------------- File structure ------------------------------------------------

Nov 15, 2022
Boost.GIL - Generic Image Library | Requires C++11 since Boost 1.68
Boost.GIL - Generic Image Library | Requires C++11 since Boost 1.68

Documentation GitHub Actions AppVeyor Azure Pipelines CircleCI Regression Codecov Boost.GIL Introduction Documentation Requirements Branches Community

Nov 24, 2022
cuehttp is a modern c++ middleware framework for http(http/https)/websocket(ws/wss).

cuehttp 简介 cuehttp是一个使用Modern C++(C++17)编写的跨平台、高性能、易用的HTTP/WebSocket框架。基于中间件模式可以方便、高效、优雅的增加功能。cuehttp基于boost.asio开发,使用picohttpparser进行HTTP协议解析。内部依赖了nl

Dec 17, 2022
HTTP/HTTPS REST Client C Library

https_client HTTP/HTTPS REST Client C Library This library is a tiny https client library. it use only small memory(default read buffer size(H_READ_SI

Dec 20, 2022
Graphical small-internet client for windows, linux, MacOS X and BSDs. Supports gemini, http, https, gopher, finger.
Graphical small-internet client for windows, linux, MacOS X and BSDs. Supports gemini, http, https, gopher, finger.

Graphical small-internet client for windows, linux, MacOS X and BSDs. Supports gemini, http, https, gopher, finger.

Dec 30, 2022
Pushpin is a reverse proxy server written in C++ that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services.
Pushpin is a reverse proxy server written in C++ that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services.

Pushpin is a reverse proxy server written in C++ that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services. The project is unique among realtime push solutions in that it is designed to address the needs of API creators. Pushpin is transparent to clients and integrates easily into an API stack.

Jan 2, 2023
Gromox - Groupware server backend with MAPI/HTTP, RPC/HTTP, IMAP, POP3 and PHP-MAPI support for grommunio

Gromox is the central groupware server component of grommunio. It is capable of serving as a replacement for Microsoft Exchange and compatibles. Conne

Dec 26, 2022
A collection of C++ HTTP libraries including an easy to use HTTP server.
A collection of C++ HTTP libraries including an easy to use HTTP server.

Proxygen: Facebook's C++ HTTP Libraries This project comprises the core C++ HTTP abstractions used at Facebook. Internally, it is used as the basis fo

Jan 4, 2023
Dec 15, 2022
websocket and http client and server library, coming with ws, a command line swiss army knife utility

Hello world IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use an

Jan 5, 2023