A C++11 RESTful web server library

Overview

Served

Served Logo

Build Status

Overview

Served is a C++ library for building high performance RESTful web servers.

Served builds upon Boost.ASIO to provide a simple API for developers to create HTTP services in C++.

Features:

  • HTTP 1.1 compatible request parser
  • Middleware / plug-ins
  • Flexible handler API
  • Cross-platform compatible

Installation

Requirements

Building

$ git clone [email protected]:meltwater/served.git
$ mkdir served.build && cd served.build
$ cmake ../served && make

Or, using bazel:

$ git clone [email protected]:meltwater/served.git
$ cd served
$ bazel build :served
$ bazel test :served-test

Getting Started

The most basic example of creating a server and handling a HTTP GET for the path /hello:

#include <served/served.hpp>

int main(int argc, char const* argv[]) {
	// Create a multiplexer for handling requests
	served::multiplexer mux;

	// GET /hello
	mux.handle("/hello")
		.get([](served::response & res, const served::request & req) {
			res << "Hello world!";
		});

	// Create the server and run with 10 handler threads.
	served::net::server server("127.0.0.1", "8080", mux);
	server.run(10);

	return (EXIT_SUCCESS);
}

To test the above example, you could run the following command from a terminal:

$ curl http://localhost:8080/hello -ivh

You can also use named path variables for REST parameters:

mux.handle("/users/{id}")
	.get([](served::response & res, const served::request & req) {
		res << "User: " << req.params["id"];
	});

To test the above example, you could run the following command from a terminal:

$ curl http://localhost:8080/users/dave -ivh

If you need to be more specific, you can specify a pattern to use to validate the parameter:

mux.handle("/users/{id:\\d+}")
	.get([](served::response & res, const served::request & req) {
		res << "id: " << req.params["id"];
	});

To test the above example, you could run the following command from a terminal:

$ curl http://localhost:8080/users/1 -ivh

Method handlers can have arbitrary complexity:

mux.handle("/users/{id:\\d+}/{property}/{value:[a-zA-Z]+")
	.get([](served::response & res, const served::request & req) {
		// handler logic
	});

If you want to automatically log requests, you could use a plugin (or make your own):

#include <served/plugins.hpp>
// ...
mux.use_after(served::plugin::access_log);

You can also access the other elements of the request, including headers and components of the URI:

mux.handle("/posts/{id:\\d+}")
	.post([](served::response & res, const served::request & req) {
		if (req.header("Content-Type") != "application/json") {
			served::response::stock_reply(400, res);
			return;
		}
		res << req.url().fragment();
	});

Compile Options

Option Purpose
SERVED_BUILD_SHARED Build shared library
SERVED_BUILD_STATIC Build static library
SERVED_BUILD_TESTS Build unit test suite
SERVED_BUILD_EXAMPLES Build bundled examples
SERVED_BUILD_DEB Build DEB package (note: you must also have dpkg installed)
SERVED_BUILD_RPM Build RPM package (note: you must also have rpmbuild installed)

System Compatibility

OS Compiler Status
Linux GCC 4.8 Working
OSX Clang 3.5 Working

TODO

  • Chunked encoding support

Contributing

Pull requests are welcome.

Authors

Copyright

See LICENSE.md document

Issues
  • Configure blocking nature for server run

    Configure blocking nature for server run

    Hi @Jeffail

    All the examples are implemented using a blocking run call.

    served::multiplexer mux;
    ...
    served::net::server server("127.0.0.1", "8123", mux);
    server.run(10);
    

    I was wondering if you have any suggestion on how to bind and start serving without a blocking call. Similar to:

    served::multiplexer mux;
    ...
    served::net::server server("127.0.0.1", "8123", mux);
    server.start(10); // maybe do_accept?
    // Do other stuff
    server.stop();
    

    May I just focus on running this in another thread?

    I can maybe look deeper to boost io_service but wanted to have your thoughts first.

    Congrats for such a great lib! Luis

    opened by luismartingil 8
  • WIP: Change enum style to prevent name clashes

    WIP: Change enum style to prevent name clashes

    Hi again :)

    The library now builds on Windows and with the Android NDK toolchain ( BTW, I also successfully tested on iOS, but I didn't need to make any changes for that to work).

    Unfortunately I had to change the style of the enums, which is a rather disruptive change. The reason for this is that certain windows headers (annoyingly) defines the MACROs ERROR and DELETE. Another way of fixing this issue would be to use the directive #undef, but to me it seems unsafe and intrusive to undefine such macros - I guess they could be used somewhere.

    I would also like to change status.hpp to be an enum and then use this new style for consistency - but that is a bit tedious work, so I will only do it if you like the idea :)

    Let me know what you think.

    opened by jpihl 5
  • Replace RE2 with std::regex

    Replace RE2 with std::regex

    Hi,

    I posted issue #33, but since I didn't get any response I just went with the simplest approach and removed RE2. I hope this is something you have interest in.

    Not having RE2 greatly simplifies porting this library to multiple platforms.

    The following work has been done in this PR:

    • Replaced RE2 with std::regex
    • Removed ZeroMQ cmake script (it seemed to not be used anywhere?)
    • Fixed bug in server.cpp where parameters was passed in an incorrect order.
    • Started work on Windows support:
      • Remove unused imports not available on windows.
      • Fix issues reported by MSVC (Still missing some, I will correct these in a different PR)

    I hope you find this work useful.

    opened by jpihl 4
  • Conan package

    Conan package

    Hello, Do you know about Conan? Conan is modern dependency manager for C++. And will be great if your library will be available via package manager for other developers.

    Here you can find example, how you can create package for the library.

    If you have any questions, just ask :-)

    opened by zamazan4ik 4
  • Curl (7)  Failed to connect

    Curl (7) Failed to connect

    I am trying to get the hang of served so I downloaded the sample hello world from here https://github.com/datasift/served/tree/master/src/examples/hello_world . I built using the CMakeLists.txt and every curl attempt I make is giving me a curl (7) error. I am running this on OS X El Capitan. Any ideas on how to fix this? screen shot 2016-08-02 at 11 57 53 am screen shot 2016-08-02 at 11 57 36 am

    opened by leoul16 4
  • Is served already captured  the SIGTERM ?

    Is served already captured the SIGTERM ?

    I want to capture SIGTERM signal. But I found when I USE RestfulServer ,I can't capture the SIGTERM signal. Is served already captured the SIGTERM ?Thank you!

    opened by AppleWeng 4
  • Fix two name clashes with Windows includes

    Fix two name clashes with Windows includes

    ERROR is a macro in wingdi.h. It can be avoided by defining NOGDI at build level. DELETE is a macro in winnt.h. It has to be undefined.

    Unfortunately I don't see a better fix except renaming the enum members.

    opened by plule-ansys 3
  • Trivial app segfaults when there are more than two routes

    Trivial app segfaults when there are more than two routes

    This trivial served app below segfaults immediately when there are more than two routes. It works fine as long as only /route1 and /route2 are present, but as soon as I add /route3, it segfaults.

    This does not happen if served is built with build type set to Debug. I have also tried building served with build type set to RelWithDebInfo and running the app in a debugger. The debugger pointed out multiplexer.cpp:139 as the culprit, which I find hard to believe since it's just std::vector::push_back:

    _handler_candidates.push_back(
    	path_handler_candidate(get_segments(path), served::methods_handler(_base_path + path, info), path));
    

    The app:

    #include <served/plugins.hpp>
    #include <served/served.hpp>
    
    int main(int, char **) {
        served::multiplexer mux;
        mux.use_after(served::plugin::access_log);
        mux.handle("/route1").get([](served::response &response, const served::request &) {
            response.set_body("1");
        });
        mux.handle("/route2").get([](served::response &response, const served::request &) {
            response.set_body("version2");
        });
        mux.handle("/route3").get([](served::response &response, const served::request &) {
            response.set_body("3");
        });
        served::net::server server("127.0.0.1", "8080", mux);
        server.run();
        return 0;
    }
    

    If I comment out

        mux.handle("/route3").get([](served::response &response, const served::request &) {
            response.set_body("3");
        });
    

    it works fine, but with three or more routes, boom!

    opened by ghost 3
  • random chrashes/keep alive

    random chrashes/keep alive

    Using msvc 14 and win10 i get some random crashes/heap corruptions. boost version is 1.6.0. To get it to work in msvc i had to rewrite url::decode and fix some char[dynamicalloc] things in multiplexer. Those rewrites are probably not causing the issue. If you are interested i can send you the code. i have done quite the same implementation as you did (boost asio example) in another project with keep alive and dropping the connection when currently active caused kind of the same corruptions (i cannot access this code anymore due to i left this company).

    the exception appears here:

    server.exe!boost::asio::detail::buffer_cast_helper(const boost::asio::const_buffer & b) Line 276 C++ server.exe!boost::asio::buffer_cast<void const * __ptr64>(const boost::asio::const_buffer & b) Line 435 C++ server.exe!boost::asio::detail::buffer_sequence_adapterboost::asio::const_buffer,boost::asio::const_buffers_1::validate(const boost::asio::const_buffers_1 & buffer_sequence) Line 255 C++ server.exe!boost::asio::detail::win_iocp_socket_send_opboost::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,void (boost::system::error_code, unsigned __int64) > >::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned __int64 bytes_transferred) Line 74 C++ server.exe!boost::asio::detail::win_iocp_operation::complete(boost::asio::detail::win_iocp_io_service & owner, const boost::system::error_code & ec, unsigned __int64 bytes_transferred) Line 47 C++ server.exe!boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 406 C++ server.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164 C++ server.exe!boost::asio::io_service::run() Line 59 C++ server.exe!served::net::server::run::__l7::() Line 86 C++

    In addition to that i dont see any implementation for http keep alive. Please correct me if iam wrong.

    bug 
    opened by martinlierschof 3
  • served: support building both static and shared libraries

    served: support building both static and shared libraries

    Building both static and shared targets fails with the following error:

    CMake Error at src/served/CMakeLists.txt:79 (ADD_LIBRARY):                                                                           
    ADD_LIBRARY cannot create target "served" because another target with the                                                          
    same name already exists.  The existing target is a static library created                                                         
    in source directory "/media/SPHEREA/Git/tns-mars_aisc/served/src/served".                                                          
    See documentation for policy CMP0002 for more details.                                                                             
    

    Correction validated with :

    cmake -DSERVED_BUILD_SHARED=ON -DSERVED_BUILD_STATIC=ON -DSERVED_BUILD_EXAMPLES=OFF -DSERVED_BUILD_RPM=ON ../served
    make
    

    Resulting RPM contents to validate the release:

    make package
    rpm -qlp ./libserved-*.rpm
    
    /usr/include/served
    /usr/include/served/methods.hpp
    /usr/include/served/methods_handler.hpp
    /usr/include/served/multiplexer.hpp
    /usr/include/served/mux
    /usr/include/served/mux/empty_matcher.hpp
    /usr/include/served/mux/matchers.hpp
    /usr/include/served/mux/regex_matcher.hpp
    /usr/include/served/mux/segment_matcher.hpp
    /usr/include/served/mux/static_matcher.hpp
    /usr/include/served/mux/variable_matcher.hpp
    /usr/include/served/net
    /usr/include/served/net/connection.hpp
    /usr/include/served/net/connection_manager.hpp
    /usr/include/served/net/server.hpp
    /usr/include/served/parameters.hpp
    /usr/include/served/plugins.hpp
    /usr/include/served/request.hpp
    /usr/include/served/request_error.hpp
    /usr/include/served/request_parser.hpp
    /usr/include/served/request_parser_impl.hpp
    /usr/include/served/response.hpp
    /usr/include/served/served.hpp
    /usr/include/served/status.hpp
    /usr/include/served/uri.hpp
    /usr/include/served/version.hpp
    /usr/lib/libserved.a
    /usr/lib/libserved.so
    /usr/lib/libserved.so.1.4
    /usr/lib/pkgconfig
    /usr/lib/pkgconfig/served.pc
    
    opened by AdrianDC 2
  • PSA: Plan to move to new organisation

    PSA: Plan to move to new organisation

    Served is going to be migrating to a new organisation at https://github.com/meltwater. I have never done this before but as I understand it the current github URL github.com/datasift/served will automatically forward to the new one at github.com/meltwater/served once the move has happened. I am hoping this means no broken builds for anyone.

    If you experience any issues from this move, or have any thoughts to contribute please post them here.

    PSA 
    opened by Jeffail 2
  • Handle same path for POST and get throws Error

    Handle same path for POST and get throws Error

    Describe the bug

    My REST server is using get for getting Informations and POST to update. But if I am using GET and POST for /settings then it will throw a served::request_error when I try to GET Request for Settings the REST Client says Method not allowed.

    Steps to reproduce

    void KSecureDesktopServer::initREST() {
       //General Settings
        served::multiplexer& mux = this->multiplexer;
        auto* sender = this;
        mux.handle("/settings").get([this](served::response& res, const served::request& req) {
           this->getSettings(res, req);  //throws an exception
            });
        mux.handle("/settings").post([this](served::response& res, const served::request& req) {
            this->postSettings(res, req); }); // works
        //Get User Info
        mux.handle("/user").get([this](served::response& res, const served::request& req) {
           // this->getUser(res, req); 
            int i = 0;
            res << "SUCCESS"; //works
            }
        );
      // mux.handle("/user").post([this](served::response& res, const served::request& req) {this->postUser(res, req); });
       // mux.handle("/user").put([this](served::response& res, const served::request& req) {this->putUser(res, req); });
        //mux.handle("/user").del([this](served::response& res, const served::request& req) {this->deleteUser(res, req); });
        //Channels
        //mux.handle("/channel").get([this](served::response& res, const served::request& req) {this->getChannel(res, req); });
        //mux.handle("/channel").post([this](served::response& res, const served::request& req) {this->postChannel(res, req); });
        //mux.handle("/channel").put([this](served::response& res, const served::request& req) {this->putChannel(res, req); });
        //mux.handle("/channel").del([this](served::response& res, const served::request& req) {this->deleteChannel(res, req); });
    
        this->restServer = std::make_unique<served::net::server>("127.0.0.1", "8080", mux);
       
        this->restServer->run(10,false);
    }
    

    Multiplexer is a Class member and net::server is a smart pointer.

    Expected behavior

    can handle both requests

    Environment (anything that would help us investigate the bug)

    Windows 10 x64 Visual Studio 2019 Community Edition

    opened by seppy87 0
  • Issues compiling hello world

    Issues compiling hello world

    After running the install steps with cmake from the README's building steps, i am met with the below errors:

    /usr/bin/ld: /tmp/ccb5Bytw.o: in function `main::{lambda(served::response&, served::request const&)#1}::operator()(served::response&, served::request const&) const':
    main.cpp:(.text+0x76): undefined reference to `served::response::operator<<(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
    /usr/bin/ld: /tmp/ccb5Bytw.o: in function `main':
    main.cpp:(.text+0x11a): undefined reference to `served::multiplexer::multiplexer()'
    /usr/bin/ld: main.cpp:(.text+0x192): undefined reference to `served::multiplexer::handle(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    /usr/bin/ld: main.cpp:(.text+0x1b6): undefined reference to `served::methods_handler::get(std::function<void (served::response&, served::request const&)>)'
    /usr/bin/ld: main.cpp:(.text+0x2d3): undefined reference to `served::net::server::server(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, served::multiplexer&, bool)'
    /usr/bin/ld: main.cpp:(.text+0x328): undefined reference to `served::net::server::run(int, bool)'
    /usr/bin/ld: /tmp/ccb5Bytw.o: in function `served::net::server::~server()':
    main.cpp:(.text._ZN6served3net6serverD2Ev[_ZN6served3net6serverD5Ev]+0x2e): undefined reference to `served::net::connection_manager::~connection_manager()'
    collect2: error: ld returned 1 exit status
    

    seems like it is a linker error? i am compiling with g++ -std=c++11 main.cpp -Iinclude -Iserved/src/served -lboost_system -lpthread from the directory i cloned the served project into.

    i will try building with blaze tomorrow to see if this resolves it

    opened by evanugarte 3
  • Unable to send query parameters

    Unable to send query parameters

    Hi, I am not able to send query parameters. I tried this:

    mux.handle("api/moveby/{x}")
    	.post([](served::response & res, const served::request & req) {
                std::string x = req.params["x"]; // gets x from path
                std::string y = req.query["y"]; // gets nothing
            }
    

    I am using curl: curl -d y=2 localhost:8080/api/moveby/1

    No matter what I do I can't retrieve it. And I don't really want to use path params.

    opened by rehovicova 1
Owner
Meltwater
Welcome to Outside Insight: There’s information everywhere. We help you frame it.
Meltwater
Tntnet is a web application server for web applications written in C++.

Tntnet is a web application server for web applications written in C++.

Tommi Mäkitalo 72 Aug 1, 2022
Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications.

Restbed Restbed is a comprehensive and consistent programming model for building applications that require seamless and secure communication over HTTP

Corvusoft 1.7k Aug 6, 2022
🌱Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.

Oat++ News Hey, meet the new oatpp version 1.2.5! See the changelog for details. Check out the new oatpp ORM - read more here. Oat++ is a modern Web F

Oat++ 5.6k Aug 11, 2022
Embedded C/C++ web server

CivetWeb The official home of CivetWeb is https://github.com/civetweb/civetweb Continuous integration for Linux and macOS (Travis CI): Continuous inte

null 2.2k Aug 11, 2022
cserv is an event-driven and non-blocking web server

cserv is an event-driven and non-blocking web server. It ideally has one worker process per cpu or processor core, and each one is capable of handling thousands of incoming network connections per worker. There is no need to create new threads or processes for each connection.

null 41 Jul 2, 2022
C library to create simple HTTP servers and Web Applications.

Onion http server library Travis status Coverity status Onion is a C library to create simple HTTP servers and Web Applications. master the developmen

David Moreno Montero 1.9k Aug 10, 2022
Crow is very fast and easy to use C++ micro web framework (inspired by Python Flask)

Crow is C++ microframework for web. (inspired by Python Flask) #include "crow.h" int main() { crow::SimpleApp app; CROW_ROUTE(app, "/")([]()

Jaeseung Ha 6.9k Aug 2, 2022
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.

Cutelyst - The Qt Web Framework A Web Framework built on top of Qt, using the simple and elegant approach of Catalyst (Perl) framework. Qt's meta obje

Cutelyst 779 Aug 3, 2022
Drogon: A C++14/17 based HTTP web application framework running on Linux/macOS/Unix/Windows

English | 简体中文 | 繁體中文 Overview Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web applicat

An Tao 7.7k Aug 4, 2022
Your high performance web application C framework

facil.io is a C micro-framework for web applications. facil.io includes: A fast HTTP/1.1 and Websocket static file + application server. Support for c

Bo 1.6k Aug 2, 2022
QDjango, a Qt-based C++ web framework

QDjango - a Qt-based C++ web framework Copyright (c) 2010-2015 Jeremy Lainé About QDjango is a web framework written in C++ and built on top of the Qt

Jeremy Lainé 245 Aug 5, 2022
TreeFrog Framework : High-speed C++ MVC Framework for Web Application

Small but Powerful and Efficient TreeFrog Framework is a high-speed and full-stack web application framework based on C++ and Qt, which supports HTTP

TreeFrog Framework 1.1k Aug 7, 2022
This is a proof-of-concept of a modern C web-framework that compiles to WASM and is used for building user interfaces.

DanCing Web ?? ?? (DCW) Getting Started Dancing Web is now distributed with the Tarantella Package Manager — a tool I've made to simplify setup of pro

Danilo Chiarlone 3 Sep 11, 2021
CppCMS - High Performance C++ Web Framework

CppCMS - High Performance C++ Web Framework What is CppCMS? CppCMS is a Free High Performance Web Development Framework (not a CMS) aimed at Rapid Web

Artyom Beilis 365 Aug 2, 2022
A high performance, middleware oriented C++14 http web framework please use matt-42/lithium instead

A high performance, middleware oriented C++14 http web framework please use matt-42/lithium instead

Matthieu Garrigues 1.7k Aug 2, 2022
Embeddable Event-based Asynchronous Message/HTTP Server library for C/C++

libasyncd Embeddable Event-based Asynchronous Message/HTTP Server library for C/C++. What is libasyncd? Libasyncd is an embeddable event-driven asynch

Seungyoung 165 May 25, 2022
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design

Microsoft 7k Aug 8, 2022
Experimental, scalable, high performance HTTP server

Lwan Web Server Lwan is a high-performance & scalable web server. The project web site contains more details. Build status OS Arch Release Debug Stati

Leandro A. F. Pereira 5.6k Aug 3, 2022
A lightweight Bedorck Dedicated Server Plugin Loader

LiteLoader 简体中文 A lightweight Bedorck Dedicated Server Plugin Loader Based on BedrockX Install Download LiteLoader from Releases or Actions, unzip it

null 420 Aug 6, 2022