Skip to content

antoniuflr/HTTP-Client-for-a-REST-API

Repository files navigation

HTTP Client for a REST API

A command-line HTTP client written in C++ that talks to a remote REST API simulating an online movie library. No HTTP libraries — sockets only. JSON parsing is handled by nlohmann/json, which is bundled in the repo.

The server lives at 63.32.125.183:8081. Two classes of users exist: admin accounts (manage normal users) and normal user accounts (manage movies and collections).


Build

make

Produces a client binary. Clean with make clean.


Usage

./client

Type commands one per line. The client opens a fresh TCP connection for each command, sends the request, reads the response, and closes the socket. The only exception is add_collection, which needs one connection to create the collection and then one connection per movie added to it (the server only accepts one movie per request).


Commands

Admin

Command What it does
login_admin Prompts username and password, logs in as admin. Sets a session cookie.
add_user Creates a normal user under the logged-in admin. Prompts username and password.
get_users Lists all normal users belonging to the admin.
delete_user Deletes a normal user by username.
logout_admin Logs out the admin session, clears cookies and JWT.

Normal user

Command What it does
login Prompts admin_username, username, password. Sets session cookie.
get_access Requests a JWT token granting library access.
get_movies Lists all movies (requires JWT).
get_movie Shows full details of a movie by id (requires JWT).
add_movie Adds a movie. Prompts title, year, description, rating (requires JWT).
update_movie Updates a movie by id with the same fields (requires JWT).
delete_movie Deletes a movie by id (requires JWT).
get_collections Lists all collections (requires JWT).
get_collection Shows a collection's movies by id (requires JWT).
add_collection Creates a collection and bulk-adds movies. Prompts title, num_movies, then movie_id[i] per movie.
delete_collection Deletes a collection by id. Must be the owner.
add_movie_to_collection Adds one movie to an existing collection. Prompts collection_id and movie_id.
delete_movie_from_collection Removes a movie from a collection. Prompts both IDs.
logout Logs out the normal user session.

Other

Command What it does
exit Quits the program.

How it works

Connection model

Each iteration of the main loop in client.cpp:

  1. Opens a TCP socket and connects to the server.
  2. Reads a command from stdin.
  3. Builds the HTTP request string in memory.
  4. Sends it and reads the full response (re-reallocs the buffer if the response is larger than BUFSIZ).
  5. Parses and prints the result, then closes the socket.

The connection is closed after every request (Connection: close). This matches what the server side expects.

Session state

Two pieces of state are kept across commands:

  • cookies — an unordered_map<string, string> populated from Set-Cookie headers. Sent back on every request in a Cookie: header.
  • jwt — a raw char * extracted from the {"token":"..."} field when get_access succeeds. Sent as Authorization: Bearer <token> on any library request.

On logout or logout_admin, both are cleared.

Request building (requests.cpp)

Four builders exist: compute_get_request, compute_post_request, compute_put_request, and compute_delete_request. They write directly into a heap-allocated char buffer using sprintf and strcat, appending headers line by line with \r\n after each. The cookie map is serialised into a single Cookie: header (key=value pairs joined by ; ).

POST and PUT requests also write Content-Type and Content-Length headers, then append the body after the blank line.

Response parsing (client_lib.cpp)

recv_resp reads from the socket in BUFSIZ chunks until recv returns 0, growing the buffer with realloc as needed.

read_resp then:

  • Checks for a {"message":...} or {"error":...} JSON field and prints it directly.
  • For commands that return structured data (get_users, get_movies, get_movie, etc.), it seeks past the \r\n\r\n header terminator and feeds the body into nlohmann::json::parse.

HTTP status codes between 200–299 are treated as success; everything else as an error. interpret_code prints either SUCCESS or ERROR with the numeric code and reason phrase.

add_collection special case

This command cannot follow the single-connection pattern because the server requires the collection to exist before movies can be added to it, and each movie addition is a separate POST on a different path. The function handle_add_collection in client_lib.cpp:

  1. Sends POST /api/v1/tema/library/collections and reads the new collection ID from the response body.
  2. Opens a new socket for each movie and sends POST /api/v1/tema/library/collections/:id/movies.

If any individual movie add fails, the loop stops early. The collection itself still exists on the server at that point.

JSON library

nlohmann/json.hpp is a single-header library included directly in the repo. It is used only for serialising request bodies (json::dump()) and deserialising response bodies (json::parse()). The choice over parson was made because nlohmann integrates cleanly with C++ std::string and operator overloading makes the code shorter.


File structure

client.cpp          — main loop: socket lifecycle, command dispatch
client_lib.hpp      — constants, path macros, command IDs, function declarations
client_lib.cpp      — command handlers, request builders, response parser
requests.cpp        — low-level HTTP message assembly (GET/POST/PUT/DELETE)
helpers.cpp         — socket helpers (send_to_server, compute_message, etc.)
buffer.cpp/.hpp     — dynamic byte buffer used by receive_from_server
util.h              — DIE macro
nlohmann/           — bundled JSON library
Makefile

About

A command-line HTTP client written in C++ that talks to a remote REST API simulating an online movie library.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages