Building HTTP Service in C++ (Using Modern Tools)

hi_artem

Artem

Posted on December 5, 2020

Building HTTP Service in C++ (Using Modern Tools)

Today I will show you how to build an HTTP service in C++ using modern tools. The point of this article is to show how easy (or hard) it is to setup an environment for cross-platform C++ development, and package the binary in one of the modern distribution formats, container.

First, a disclaimer:

I am not a professional C++ developers, and any opinions shared in this tutorial should not be treated as absolute truth!

That said, since I am not profession C++ developer, this tutorial is suitable for "everyone-and-their-mother". The shell commands shown should work in most recent versions of Linux and OSX. Windows users can find themselves making some extra research, but overall the tools used are cross-platform.

Requirements

First things first, install the following tools:

  • CMake - system designed to build cross-platform software.
  • Conan - C/C++ package manager.
  • Make - tool controlling the generation of executables.
  • Docker - set of tools for OS-level virtualization.

What are we building?

The HTTP service and is mostly based on this particular example from Boost Beast library. I modified it, replacing plaintext responses with json, and adding Boost Log library.

Setting up development tools

Start by creating a src directory in the root of your project, and putting this C++ file inside:

mkdir src
curl -o src/main.cpp https://gist.githubusercontent.com/hi-artem/07e896d5d7b43d1cf63cf58e8665524b/raw/73d3148603c16e0505af52071b7658e6eda967b4/main.cpp
Enter fullscreen mode Exit fullscreen mode

Although Boost is one of the well supported libraries, I always struggle manually installing it on my development machine. This is where Conan comes into play. For people familiar with Node, think of Conan as NPM or Yarn for C/C++.

Create conanfile.txt with the following content:

[requires]
boost/1.74.0

[generators]
cmake
Enter fullscreen mode Exit fullscreen mode

Next, configure CMake to let it know about location of the C++ source file, and enable Conan integration. It can be done by creating CMakeLists.txt looking like so:

cmake_minimum_required(VERSION 3.10)

project(http-service VERSION 0.0.1)
set(CMAKE_CXX_STANDARD 14)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

add_executable(http-service src/main.cpp)
target_link_libraries(http-service ${CONAN_LIBS})
Enter fullscreen mode Exit fullscreen mode

Building executable

This is all you need to build and run the project locally! The following shell script contains all the required build commands:

#!/bin/bash

# remove all build folder if exists
rm -rf build

# create new build folder
mkdir build && cd build

# install dependencies
conan install ..

# generate build files
cmake ..

# generate executable
make
Enter fullscreen mode Exit fullscreen mode

Once build succeded the service can be started by running:

./build/bin/http-service 0.0.0.0 8080
Enter fullscreen mode Exit fullscreen mode

You should see something like:

[2020-12-05 13:17:27.928789] [0x000000011670fdc0] [info]    Service is listening on 0.0.0.0:8080
Enter fullscreen mode Exit fullscreen mode

Use curl or web browser, to test that service is running. For example:

curl -i 0.0.0.0:8000/api/status

## Should return something similar to:
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 60

{"status":"OK","request_count":"1","timestamp":"1607196274"}
Enter fullscreen mode Exit fullscreen mode

Containerizing service

The previous steps configured development environment, however modern stacks require application to be packaged as container so it can be run by one of the orchestrators, like Kubernetes or Nomad.

Since we are using Docker to containerize the service, let's start by creating Dockerfile:

# Create image with all required build tools
FROM ubuntu:18.04 as build-tools

RUN apt-get update && apt-get install -y \
  build-essential \
  cmake \
  python3-pip \
  && rm -rf /var/lib/apt/lists/*

RUN pip3 install conan


# Build binary
FROM build-tools as builder

WORKDIR /usr/src/service

COPY . .

WORKDIR /usr/src/service/build

RUN conan install ..
RUN cmake ..
RUN make


# Copy binary to fresh ubuntu image
FROM ubuntu:18.04 as runner

RUN groupadd -r ubuntu && useradd --no-log-init -r -g ubuntu ubuntu
USER ubuntu:ubuntu

COPY --from=builder /usr/src/service/build/bin/http-service /usr/bin/http-service
EXPOSE 8080

CMD [ "http-service", "0.0.0.0", "8080" ]
Enter fullscreen mode Exit fullscreen mode

The image is created using multi-stage build process: first, creating the image with all required tools to build the service; second, build the service; finally, copy the executable in fresh ubuntu image. The process is run as non-root user to avoid privileges escalation.

The last thing before the image build, create .dockerignore file, which serves similar purpose as .gitignore:

build
.vscode
Enter fullscreen mode Exit fullscreen mode

Finally, let's build the image. For folks no familiar with Docker, this commands will build and run the HTTP service:

docker build -t http-service .
docker run --rm --init -p 8080:8080 http-service
Enter fullscreen mode Exit fullscreen mode

As previously, use curl or web browser to test that service is running:

curl -i localhost:8000/api/status

## Should return something similar to:
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 60

{"status":"OK","request_count":"1","timestamp":"1607196274"}
Enter fullscreen mode Exit fullscreen mode

At this point, the image can be tagged and pushed in a Docker registry, from where it can be pulled by a container orchestrator.


The purposes of this article was to reduce frustration associated with setting environment for C++ development. I hope you were able to follow. If not, the source code is available at github.com/hi-artem/http-service. Let me know in comments if you have any questions.

💖 💪 🙅 🚩
hi_artem
Artem

Posted on December 5, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related