Skip to content

Repository files navigation

resizer

A small HTTP service that resizes a JPEG image to a requested size. The image is sent base64-encoded in a JSON body and returned base64-encoded in the response.

Built with libasyik (fiber-based HTTP server) and OpenCV for image processing.

API

A single endpoint:

POST /resize_image
Content-Type: application/json

Request

{
  "input_jpeg": "<base64 of the input JPEG>",
  "desired_width": 128,
  "desired_height": 128
}

Response — success (HTTP 200)

{
  "code": 200,
  "message": "success",
  "output_jpeg": "<base64 of the resized JPEG>"
}

Response — failure (HTTP 4xx / 5xx)

{
  "code": 422,
  "message": "could not decode input_jpeg as a valid image"
}
Status When
200 Image resized successfully
400 Body is not valid JSON (malformed / unparseable)
422 Valid JSON, but the content can't be processed — missing field, wrong type, invalid base64, undecodable image, or out-of-range dimensions
500 Internal server error (e.g. disk write failure)

Requirements

  • Docker (with Docker Compose)
  • git (the dependencies are git submodules)

Everything else — a C++17 toolchain, Boost 1.81, OpenCV, libasyik — is built inside the container, so nothing needs to be installed on the host.

Quick start

# 1. Clone with submodules
git clone --recurse-submodules <repo-url>
cd resizer
#    (if you already cloned without --recurse-submodules:)
git submodule update --init --recursive

# 2. Build and run
docker compose up --build

The server listens on port 8080. Try it:

B64=$(base64 -i "Lenna_(test_image).png" | tr -d '\n')

curl -s -X POST http://localhost:8080/resize_image \
  -H "Content-Type: application/json" \
  -d "{\"input_jpeg\":\"$B64\",\"desired_width\":128,\"desired_height\":128}" \
  | ./save_output.sh resized.jpg

save_output.sh decodes the output_jpeg field from the response into a file.

Running without Docker Compose

The image is self-contained (the binary is compiled into it), so plain Docker works too:

docker build -t resizer .
docker run --rm -p 8080:8080 resizer

Testing

There are two test layers.

Unit tests (GoogleTest) — exercise the resize pipeline and the status-code logic in-process:

docker compose up -d            # start the dev container
docker exec -it resizer_app bash -c "
  cmake -B build -GNinja -DRESIZER_BUILD_TESTS=ON -DLIBASYIK_ENABLE_SOCI=OFF &&
  ninja -C build resizer_tests -j2 &&
  ./build/resizer_tests"

Endpoint tests (Python, stdlib only) — send real HTTP requests to a running server and assert on status codes and response bodies, including verifying the output is actually resized to the requested dimensions:

docker compose up -d
python3 tests/test_endpoint.py            # defaults to http://localhost:8080

Continuous integration

.github/workflows/ci.yml runs on every push / pull request: it builds the Docker image (with layer caching), runs the unit tests, then starts the server and runs the endpoint tests against it.

Project layout

main.cpp              # entry point: sets up the libasyik server + route
resizer.hpp / .cpp    # the resize pipeline + request handling (the core logic)
tests/
  test_resizer.cpp    # GoogleTest unit tests
  test_endpoint.py    # HTTP integration tests
save_output.sh        # decode a response's output_jpeg into a file
CMakeLists.txt        # build configuration
Dockerfile            # self-contained build + runtime image
docker-compose.yml    # dev workflow (mounted source, rebuild on `up`)
external/             # dependencies, as git submodules
  libasyik/           #   HTTP server
  json/               #   nlohmann/json
  googletest/         #   GoogleTest (tests only)

Dependencies

Dependency How it's provided
libasyik git submodule (external/libasyik)
nlohmann/json git submodule (external/json)
GoogleTest git submodule (external/googletest)
Boost 1.81 compiled from source in the Docker image
OpenCV apt package in the Docker image

Design notes

  • process_resize (pure) vs handle_resize (HTTP glue). All logic lives in process_resize, which takes a JSON string and returns a {status, body} pair — no dependency on the HTTP framework, so it's fully unit-testable. handle_resize is a thin adapter that copies that result onto the libasyik response.
  • Errors as exceptions. Each pipeline step throws http_error(code, msg) on failure; a single try/catch in process_resize maps every failure (plus the exceptions thrown by nlohmann/cppcodec) to the right HTTP status.
  • Diagnostic files. On a successful request the server also writes input.jpg (decoded input) and output.jpg (resized output) to its working directory, for easy inspection. They are overwritten per request.

About

A small HTTP service that resizes a JPEG image to a requested size

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages