/via-httplib

A library for embedding an HTTP or HTTPS server in C++ applications.

Primary LanguageC++Boost Software License 1.0BSL-1.0

via-httplib: A C++ HTTP Library

C/C++ CI License

A header-only library for embedding HTTP or HTTPS, IPV6 and IPV4 servers in C++ applications.

via-httplib is an asynchronous communications library built upon asio (either boost or standalone) to enable simple, secure and efficient HTTP/HTTPS servers to be built that comply with rfc7230 wherever possible.

Requirements

  • A C++17 compliant compiler. This version requires a complier that supports string_view.
    It's been tested with MSVC 2022, GCC 12.3.0 and MinGw 11.2.0.
    C++11 versions are available in tags 1.6.0 and lower.

  • The asio C++ library, either standalone asio or boost asio.

  • For: multithreading, authentication and/or the request router, the relevant boost libraries are required.

  • For HTTPS: the OpenSSL library, see openssl.

  • For C++ code documentation: Doxygen

Getting Started

Download the latest tagged version of via-httplib from Github and follow the instructions here: Make.

via-http lib depends on the standalone asio or boost libraries.
If boost is not installed on your machine then download the latest package from boost and follow the instructions here: boost getting started. Otherwise standalone asio can be downloaded from: asio.

If you require an HTTPS server or client then you must also install the OpenSSL library.
Please note that a plain HTTP server does not require OpenSLL.

The Server User Guide explains how to use the library to create HTTP servers and the Client User Guide explains how to use the library to create HTTP clients.

An example https server docker image can be built using the following commands from this directory:

docker build . -t via-http-server:0.1

Example HTTP Server

The following code implements an HTTP server that responds to GET requests to the /hello and /hello/:name endpoints:

#include "via/comms/tcp_adaptor.hpp"
#include "via/http_server.hpp"
#include "via/http/request_router.hpp"
#include <iostream>

/// Define an HTTP server using std::string to store message bodies
typedef via::http_server<via::comms::tcp_adaptor, std::string> http_server_type;
typedef http_server_type::http_connection_type http_connection;
typedef http_server_type::http_request http_request;

namespace
{
  using namespace via::http;

  /// /hello request handler
  tx_response get_hello_handler(http_request const&, //request,
                                Parameters const&, //parameters,
                                std::string const&, // data,
                                std::string &response_body)
  {
    response_body += "Hello, whoever you are?!";
    return tx_response(response_status::code::OK);
  }

  /// /hello/:name request handler
  tx_response get_hello_name_handler(http_request const&, //request,
                                     Parameters const& parameters,
                                     std::string const&, // data,
                                     std::string &response_body)
  {
    response_body += "Hello, ";
    auto iter(parameters.find("name"));
    if (iter != parameters.end())
      response_body += iter->second;

    return tx_response(response_status::code::OK);
  }
}

int main(int /* argc */, char *argv[])
{
  std::string app_name(argv[0]);
  unsigned short port_number(via::comms::tcp_adaptor::DEFAULT_HTTP_PORT);
  std::cout << app_name << ": " << port_number << std::endl;

  try
  {
    // The asio io_context.
    boost::asio::io_context io_context;

    // Create the HTTP server
    http_server_type http_server(io_context);

    // Attach the request method handlers
    http_server.request_router().add_method("GET", "/hello", get_hello_handler);
    http_server.request_router().add_method(request_method::GET, "/hello/:name",
                                            get_hello_name_handler);

    // Accept connections (both IPV4 and IPV6) on the default port (80)
    boost::system::error_code error(http_server.accept_connections());
    if (error)
    {
      std::cerr << "Error: "  << error.message() << std::endl;
      return 1;
    }

    // Start the server
    io_context.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception:"  << e.what() << std::endl;
    return 1;
  }

  return 0;
}

Documentation

Document Description
Build Guide How to build the library.
Server User Guide How to use the library to create HTTP servers.
Client User Guide How to use the library to create HTTP clients.
Security Guide HTTP Server security considerations.
Design The library design.
examples/server Example HTTP & HTTPS servers.
examples/client Example HTTP & HTTPS clients.

Directory Structure

Directory Contents
via The via-httplib API classes: http_server, http_connection and http_client.
examples/server Example HTTP & HTTPS servers.
examples/client Example HTTP & HTTPS clients.
tests Unit tests for the HTTP parsers and encoders.
docs The User Guides and design documents.
docs/html Doxygen output directory. Created by running doxygen Doxyfile in the docs directory.

License

Licensed under the Boost License, Version 1.0, as per Boost.
You may obtain a copy of the License at: https://www.boost.org/LICENSE_1_0.txt

Acknowledgements

Thanks to:

  • Neil Tisdale for encouraging and inspiring me to create the library
  • Louis Nayegon for helping to develop it and recommending GitHub
  • Adam Leggett for helping to identify and fix security, efficiency and CMake issues
  • Christopher Kohlhoff for the asio library, without which, this library wouldn't exist.