SkillAgentSearch skills...

Malloy

A cross-platform C++23 library providing embeddable server & client components for HTTP and WebSocket.

Install / Use

/learn @Tectu/Malloy

README

<p align="center"> <img height="180" src="https://raw.githubusercontent.com/Tectu/malloy/main/doc/logo.svg"/> </p> <p align="center"> <img src="https://img.shields.io/badge/C%2B%2B-23-blue.svg" alt="standard"/> <img src="https://img.shields.io/badge/License-BSD-blue.svg" alt="license"/> <a href="https://repology.org/project/malloy/versions"> <img src="https://repology.org/badge/tiny-repos/malloy.svg" alt="Packaging status"> </a> </p>

Packages

Packaging status

Overview

Malloy is a small, embeddable HTTP & WebSocket server & client built on top of boost.

The main use case for this library is a C++ project which needs to embedd an HTTP and/or WebSocket server and/or client.

This library is being used successfully on:

  • Windows (with both MSVC and MinGW)
  • Linux (Ubuntu, Debian, Fedora, ...)
  • MacOS
  • FreeBSD

Features

The following list provides an overview of the currently implemented features. Some of these are optional and can be enabled/disabled.

  • High-level controller to setup I/O context, SSL context, worker threads and more
  • URL parsing support
  • HTTP
    • Plain or TLS (SSL) connections
    • Cookies
    • Sessions
    • Upgrading connections to WebSocket
    • Client
      • Response filters
      • File downloads directly to disk
    • Server
      • Routing
        • Simple handlers (useful for building REST APIs)
          • Target matching via regex
          • Capturing groups via regex
        • Sub-routers (nested/chained routers)
        • Redirections
        • File serving locations
          • Optional cache-control directives
        • Preflight responses
        • Access policies
          • HTTP basic auth
          • Custom access policies
        • Websocket endpoints (with auto-upgrade from HTTP)
      • Connection logging
      • Request filters
  • WebSocket
    • Client
    • Server
    • Connections upgradable from HTTP
  • HTML
    • Forms
      • Supported encoding types
        • application/x-www-form-urlencoded
        • multipart/form-data
        • text/plain
      • Parsing
      • Rendering

Licensing

This library is BSD-3-Clause licensed. Dependencies ship with their own licensing models.

Requirements

Building (and using) this library requires:

  • A C++23 capable compiler
  • CMake 3.23 or newer

Dependencies

Required:

  • Boost 1.86.0 or newer (older versions may work but are no longer actively tested)
  • spdlog

Optional:

  • OpenSSL

Examples

A variety of examples can be found in the /examples directory. You should definitely check those out! What follows are snippets for a simple HTTP server and a simple HTTP client.

HTTP Server:

int main()
{
    // Create malloy controller config
    malloy::server::routing_context::config cfg;
    cfg.interface   = "127.0.0.1";
    cfg.port        = 8080;
    cfg.doc_root    = "/path/to/http/docs"
    cfg.num_threads = 5;
    cfg.logger      = std::make_shared<spdlog::logger>();

    // Create malloy controller
    malloy::server::routing_context c{cfg};

    // Create the router
    auto& router = c.router();
    {
        using namespace malloy::http;

        // A simple GET route handler
        router.add(method::get, "/", [](const auto& req) {
            response res{status::ok};
            res.body() = "<html><body><h1>Hello World!</h1><p>some content...</p></body></html>";
            return res;
        });

        // Add a route to an existing file
        router.add(method::get, "/file", [](const auto& req) {
            return generator::file(examples_doc_root, "index.html");
        });

        // Add a route to a non-existing file
        router.add(method::get, "/file_nonexist", [](const auto& req) {
            return generator::file(examples_doc_root, "/some_nonexisting_file.xzy");
        });

        // Add some redirections
        router.add_redirect(status::permanent_redirect, "/redirect1", "/");
        router.add_redirect(status::temporary_redirect, "/redirect2", "/");

        // Add some file serving
        router.add_file_serving("/files", examples_doc_root);

        // Add a websocket echo endpoint
        router.add_websocket("/echo", [](const auto& req, auto writer) {
            std::make_shared<malloy::examples::ws::server_echo>(writer)->run(req);
        });
    }

    // Start
    start(std::move(c)).run();

    return EXIT_SUCCESS;
}

HTTP client:

malloy::awaitable<void>
example()
{
    // Create the controller config
    malloy::client::controller::config cfg;
    cfg.logger      = create_example_logger();
    cfg.num_threads = 1;

    // Create the controller
    malloy::client::controller c{cfg};

    // Start
    [[maybe_unused]] auto session = start(c);

    // Make request
    auto resp = co_await c.http_request("http://www.google.com");
    if (!resp)
        spdlog::error("error: {}", resp.error().message());
    else
        std::cout << *resp << std::endl;
}

Security

This is a work in progress and should generally be perceived as unfit for any production use.

As of today, no security research has been performed on this library.

Malloy is an open-source library provided WITHOUT any WARRANTY or GUARANTEE regarding security, safety, functionality or anything else. Use at your own risk!

Documentation

Available documentation sources:

  • API documentation (doxygen)

Doxygen

The Doxygen API documentation can be generated with little hassle:

doxygen ./Doxyfile

The generated output(s) may be found under /docs/doxygen. Simply open /docs/doxygen/html/index.html in the web browser of your choosing.

Integration

Malloy is designed to be an embeddable component for other C++ applications. As this is a CMake based project there are various ways to integrate this library into another project:

  • Via CMake's FetchContent().
  • Building the library locally, installing it on the system and using CMake's find_package().
  • Installing the corresponding package for your OS/environment and using CMake's find_package().

FetchContent()

The easiest way to integrate Malloy is via CMake's FetchContent() infrastructure:

# Change various malloy cmake options
set(MALLOY_BUILD_EXAMPLES OFF CACHE INTERNAL "")
set(MALLOY_BUILD_TESTS    OFF CACHE INTERNAL "")
set(MALLOY_BUILD_SHARED   ON  CACHE INTERNAL "")
set(MALLOY_FEATURE_CLIENT OFF CACHE INTERNAL "")
set(MALLOY_FEATURE_SERVER ON  CACHE INTERNAL "")
set(MALLOY_FEATURE_TLS    ON  CACHE INTERNAL "")

FetchContent_Declare(
    malloy
    GIT_REPOSITORY https://github.com/tectu/malloy
    GIT_TAG        main
)
FetchContent_MakeAvailable(malloy)

You may replace GIT_TAG with a commit hash or a release tag such as 1.0.0.

After fetching the content, it's only a matter of linking the malloy library target(s) to the consuming application:

target_link_libraries(
    my_application
    PRIVATE
        malloy-server       # Link malloy's server components
        malloy-client       # Link malloy's client components
)

Where my_application is your application (or library) target that should consume malloy.

Options

Various cmake options are available to control the build:

Build

| Option | Default | Description | |-------------------------|---------|-------------------------------------------------------------------------------------| | MALLOY_BUILD_EXAMPLES | ON | Whether to build examples. | | MALLOY_BUILD_TESTS | ON | Whether to build the test suite(s). | | MALLOY_BUILD_SHARED | OFF | Whether to build shared libraries. If set to OFF, static libraries will be built. |

Features

| Option | Default | Description | |-------------------------|---------|---------------------------------------------------------------------| | MALLOY_FEATURE_CLIENT | ON | Enable client features. | | MALLOY_FEATURE_SERVER | ON | Enable server features. | | MALLOY_FEATURE_HTML | ON | Whether to enable HTML support. | | MALLOY_FEATURE_TLS | OFF | Whether to enable TLS support. |

View on GitHub
GitHub Stars84
CategoryDevelopment
Updated7d ago
Forks14

Languages

C++

Security Score

100/100

Audited on Mar 20, 2026

No findings