All Projects → sprinfall → Webcc

sprinfall / Webcc

Licence: lgpl-3.0
Lightweight C++ HTTP client and server library based on Asio for embedding purpose.

Programming Languages

cpp
1120 projects
cplusplus
227 projects

Projects that are alternatives of or similar to Webcc

Cppwebframework
​The C++ Web Framework (CWF) is a MVC web framework, Open Source, under MIT License, using C++ with Qt to be used in the development of web applications.
Stars: ✭ 348 (+108.38%)
Mutual labels:  rest, webservice
Restinio
Cross-platform, efficient, customizable, and robust asynchronous HTTP/WebSocket server C++14 library with the right balance between performance and ease of use
Stars: ✭ 694 (+315.57%)
Mutual labels:  rest, asio
Restc Cpp
Modern C++ REST Client library
Stars: ✭ 371 (+122.16%)
Mutual labels:  rest, asio
asio-extensions
Additional functionality built on top of (Boost.)Asio
Stars: ✭ 16 (-90.42%)
Mutual labels:  boost, asio
Snug
Write reusable web API interactions
Stars: ✭ 108 (-35.33%)
Mutual labels:  rest, requests
Requester
Powerful, modern HTTP/REST client built on top of the Requests library
Stars: ✭ 273 (+63.47%)
Mutual labels:  rest, requests
Restclient
🦄 Simple HTTP and REST client for Unity based on Promises, also supports Callbacks! 🎮
Stars: ✭ 675 (+304.19%)
Mutual labels:  rest, requests
ufw
A minimalist framework for rapid server side applications prototyping in C++ with dependency injection support.
Stars: ✭ 19 (-88.62%)
Mutual labels:  boost, asio
Clam
Quickly turn command-line applications into RESTful webservices with a web-application front-end. You provide a specification of your command line application, its input, output and parameters, and CLAM wraps around your application to form a fully fledged RESTful webservice.
Stars: ✭ 103 (-38.32%)
Mutual labels:  rest, webservice
Sdmx Rest
This repository is used for maintaining the SDMX RESTful web services specification.
Stars: ✭ 50 (-70.06%)
Mutual labels:  rest, webservice
mtxclient
Client API library for Matrix, built on top of Boost.Asio
Stars: ✭ 21 (-87.43%)
Mutual labels:  boost, asio
Cpp Bredis
Boost::ASIO low-level redis client (connector)
Stars: ✭ 117 (-29.94%)
Mutual labels:  boost, asio
boost beast websocket echo
A collection of Demo applications to try to help you understand how Asio and Beast work
Stars: ✭ 12 (-92.81%)
Mutual labels:  boost, asio
Beast
HTTP and WebSocket built on Boost.Asio in C++11
Stars: ✭ 3,241 (+1840.72%)
Mutual labels:  boost, asio
texugo
🦡 Fast, flexible, multiplatform, lightweight and, dependency-free message gateway
Stars: ✭ 18 (-89.22%)
Mutual labels:  boost, asio
Restheart
RESTHeart - The REST API for MongoDB
Stars: ✭ 659 (+294.61%)
Mutual labels:  rest, webservice
SierraChartZorroPlugin
A Zorro broker API plugin for Sierra Chart, written in Win32 C++.
Stars: ✭ 22 (-86.83%)
Mutual labels:  boost, asio
boost-wintls
Native Windows TLS stream wrapper for use with boost::asio
Stars: ✭ 24 (-85.63%)
Mutual labels:  boost, asio
Just Api
💥 Test REST, GraphQL APIs
Stars: ✭ 768 (+359.88%)
Mutual labels:  rest, webservice
Cpp Rotor
Event loop friendly C++ actor micro-framework
Stars: ✭ 111 (-33.53%)
Mutual labels:  boost, asio

Webcc - C++ HTTP Library

NOTE:

  • legacy branch only uses limited C++11 features, so it could be built by old compilers like VS2013 and GCC 4.8.

中文版 README

Lightweight C++ HTTP client and server library based on Boost Asio for embedding purpose.

=> Build Instructions (中文版)

Git repo: https://github.com/sprinfall/webcc. Please check this one instead of the forked for the latest features.

Contents

Overview

  • Cross-platform: Windows, Linux and MacOS
  • Easy-to-use client API inspired by Python requests
  • IPv6 support
  • SSL/HTTPS support with OpenSSL (optional)
  • GZip compression support with Zlib (optional)
  • Persistent (Keep-Alive) connections
  • Data streaming
    • for uploading and downloading large files on client
    • for serving and receiving large files on server
  • Basic & Token authorization
  • Timeout control
  • Source code follows Google C++ Style
  • Automation tests and unit tests included

Client API

A Complete Example

Let's start from a complete client example:

#include <iostream>

#include "webcc/client_session.h"
#include "webcc/logger.h"

int main() {
  // Configure logger to print only to console.
  WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
  
  // Session provides convenient request APIs, stores request configurations
  // and manages persistent connenctions.
  webcc::ClientSession session;

  // Catch exceptions for error handling.
  try {
    // Send a HTTP GET request.
    auto r = session.Send(webcc::RequestBuilder{}.
                          Get("http://httpbin.org/get")
                          ());

    // Print the response data.
    std::cout << r->data() << std::endl;

  } catch (const webcc::Error& error) {
    std::cerr << error << std::endl;
  }

  return 0;
}

Request Builder

As you can see, a helper class named RequestBuilder is used to chain the parameters and finally build a request object. Please pay attention to the () operator.

URL query parameters can be easily added through Query() method:

session.Send(webcc::RequestBuilder{}.
             Get("http://httpbin.org/get").
             Query("key1", "value1").Query("key2", "value2")
             ());

Adding additional headers is also easy:

session.Send(webcc::RequestBuilder{}.
             Get("http://httpbin.org/get").
             Header("Accept", "application/json")
             ());

HTTPS

Accessing HTTPS has no difference from HTTP:

session.Send(webcc::RequestBuilder{}.Get("https://httpbin.org/get")());

NOTE: The HTTPS/SSL support requires the build option WEBCC_ENABLE_SSL to be enabled.

Invoking GitHub REST API

Listing GitHub public events is not a big deal:

auto r = session.Send(webcc::RequestBuilder{}.
                      Get("https://api.github.com/events")
                      ());

You can then parse r->data() to JSON object with your favorite JSON library. My choice for the examples is jsoncpp. But Webcc itself doesn't understand JSON nor require one. It's up to you to choose the most appropriate JSON library.

RequestBuilder provides a lot of functions for you to customize the request. Let's see more examples.

Authorization

In order to list the followers of an authorized GitHub user, you need either Basic Authorization:

session.Send(webcc::RequestBuilder{}.
             Get("https://api.github.com/user/followers").
             AuthBasic(<login>, <password>)
             ());

Or Token Authorization:

session.Send(webcc::RequestBuilder{}.
             Get("https://api.github.com/user/followers").
             AuthToken(<token>)
             ());

Keep-Alive

Though Keep-Alive (i.e., Persistent Connection) is a good feature and enabled by default, you can turn it off:

auto r = session.Send(webcc::RequestBuilder{}.
                      Get("http://httpbin.org/get").
                      KeepAlive(false)  // No Keep-Alive
                      ());

The API for other HTTP requests is no different from GET.

POST Request

A POST request needs a body which is normally a JSON string for REST API. Let's post a small UTF-8 encoded JSON string:

session.Send(webcc::RequestBuilder{}.
             Post("http://httpbin.org/post").
             Body("{'name'='Adam', 'age'=20}").Json().Utf8()
             ());

The body of a POST request could be any content other than JSON string.

It could be the binary data of a file. See Uploading Files.

It could be a form urlencoded string:

webcc::ClientSession session;
session.SetContentType("application/x-www-form-urlencoded", "utf8");

// Use UrlQuery to compose the urlencoded string.
// Don't use RequestBuilder::Query() which is dedicated to GET.
webcc::UrlQuery query;
query.Add("key1", "value1");
query.Add("key2", "value2");
// ...

auto r = session.Send(webcc::RequestBuilder{}.
                      Post("http://httpbin.org/post").
                      Body(query.ToString())
                      ());

Please see examples/form_urlencoded_client.cc for more details.

Downloading Files

Webcc has the ability to stream large response data to a file. This is especially useful when downloading files.

auto r = session.Send(webcc::RequestBuilder{}.
                      Get("http://httpbin.org/image/jpeg")
                      (), /*stream=*/true);

// Move the streamed file to your destination.
r->file_body()->Move("./wolf.jpeg");

Uploading Files

Streaming is also available for uploading:

auto r = session.Send(webcc::RequestBuilder{}.
                      Post("http://httpbin.org/post").
                      File(local/file/path)
                      ());

The file will not be loaded into the memory all at once, instead, it will be read and sent piece by piece.

Please note that Content-Length header will still be set to the true size of the file, this is different from the handling of chunked data (Transfer-Encoding: chunked).

Client API and Threads

A ClientSession shouldn't be shared by multiple threads. Please create a new session for each thread.

Example:

void ThreadedClient() {
  std::vector<std::thread> threads;

  for (int i = 0; i < 3; ++i) {
    threads.emplace_back([]() {
      webcc::ClientSession session;

      try {
        auto r = session.Send(webcc::RequestBuilder{}.
                              Get("http://httpbin.org/get")
                              ());
        std::cout << r->data() << std::endl;

      } catch (const webcc::Error&) {
      }
    });
  }

  for (auto& t : threads) {
    t.join();
  }
}

Server API

A Minimal Server

The following example is a minimal yet complete HTTP server.

Start it, open a browser with localhost:8080, you will see Hello, World! as response.

#include "webcc/logger.h"
#include "webcc/response_builder.h"
#include "webcc/server.h"

class HelloView : public webcc::View {
public:
  webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
    if (request->method() == "GET") {
      return webcc::ResponseBuilder{}.OK().Body("Hello, World!")();
    }

    return {};
  }
};

int main() {
  try {
    webcc::Server server{ boost::asio::ip::tcp::v4(), 8080 };

    server.Route("/", std::make_shared<HelloView>());

    server.Run();

  } catch (const std::exception&) {
    return 1;
  }

  return 0;
}

URL Route

The Route() method routes different URLs to different views.

You can route different URLs to the same view:

server.Route("/", std::make_shared<HelloView>());
server.Route("/hello", std::make_shared<HelloView>());

Or even the same view object:

auto view = std::make_shared<HelloView>();
server.Route("/", view);
server.Route("/hello", view);

But normally a view only handles a specific URL (see the Book Server example).

The URL could be regular expressions. The Book Server example uses a regex URL to match against book IDs.

Finally, it's always suggested to explicitly specify the HTTP methods allowed for a route:

server.Route("/", std::make_shared<HelloView>(), { "GET" });

Running A Server

The last thing about server is Run():

void Run(std::size_t workers = 1, std::size_t loops = 1);

Workers are threads which will be waken to process the HTTP requests once they arrive. Theoretically, the more workers you have, the more concurrency you gain. In practice, you have to take the number of CPU cores into account and allocate a reasonable number for it.

The loops means the number of threads running the IO Context of Asio. Normally, one thread is good enough, but it could be more than that.

Response Builder

The server API provides a helper class ResponseBuilder for the views to chain the parameters and finally build a response object. This is exactly the same strategy as RequestBuilder.

REST Book Server

Suppose you want to create a book server and provide the following operations with RESTful API:

  • Query books based on some criterias.
  • Add a new book.
  • Get the detailed information of a book.
  • Update the information of a book.
  • Delete a book.

The first two operations are implemented by BookListView deriving from webcc::View:

class BookListView : public webcc::View {
public:
  webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
    if (request->method() == "GET") {
      return Get(request);
    }
    if (request->method() == "POST") {
      return Post(request);
    }
    return {};
  }
  
private:
  // Get a list of books based on query parameters.
  webcc::ResponsePtr Get(webcc::RequestPtr request);

  // Create a new book.
  // The new book's data is attached as request data in JSON format.
  webcc::ResponsePtr Post(webcc::RequestPtr request);
};

Other operations are implemented by BookDetailView:

class BookDetailView : public webcc::View {
public:
  webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
    if (request->method() == "GET") {
      return Get(request);
    }
    if (request->method() == "PUT") {
      return Put(request);
    }
    if (request->method() == "DELETE") {
      return Delete(request);
    }
    return {};
  }
  
protected:
  // Get the detailed information of a book.
  webcc::ResponsePtr Get(webcc::RequestPtr request);

  // Update a book.
  webcc::ResponsePtr Put(webcc::RequestPtr request);

  // Delete a book.
  webcc::ResponsePtr Delete(webcc::RequestPtr request);
};

The detailed implementation is out of the scope of this README, but here is an example:

webcc::ResponsePtr BookDetailView::Get(webcc::RequestPtr request) {
  if (request->args().size() != 1) {
    // NotFound means the resource specified by the URL cannot be found.
    // BadRequest could be another choice.
    return webcc::ResponseBuilder{}.NotFound()();
  }

  const std::string& book_id = request->args()[0];

  // Get the book by ID from, e.g., the database.
  // ...

  if (<NotFound>) {
    // There's no such book with the given ID. 
    return webcc::ResponseBuilder{}.NotFound()();
  }

  // Convert the book to JSON string and set as response data.
  return webcc::ResponseBuilder{}.OK().Data(<JsonStringOfTheBook>).
      Json().Utf8()();
}

Last step, route URLs to the proper views and run the server:

int main(int argc, char* argv[]) {
  // ...

  try {
    webcc::Server server{ boost::asio::ip::tcp::v4(), 8080 };

    server.Route("/books",
                 std::make_shared<BookListView>(),
                 { "GET", "POST" });

    server.Route(webcc::R("/books/(\\d+)"),
                 std::make_shared<BookDetailView>(),
                 { "GET", "PUT", "DELETE" });

    server.Run();

  } catch (const std::exception& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }

  return 0;

Please see examples/book_server for more details.

IPv6 Support

IPv6 Server

Only need to change the protocol to boost::asio::ip::tcp::v6():

webcc::Server server{ boost::asio::ip::tcp::v6(), 8080 };

IPv6 Client

Only need to specify an IPv6 address:

auto r = session.Send(webcc::RequestBuilder{}.
                      Get("http://[::1]:8080/books").
                      ());
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].