Making GET Requests and Handling Responses

Welcome to the second lesson in our journey of Interacting with APIs in C++. In the previous lesson, we laid a strong foundation by understanding RESTful APIs and how HTTP requests facilitate interactions with them. We used curl to manually craft and send a GET request to an endpoint. Now, we are transitioning to automating this process using C++. This lesson introduces the httplib library, which allows us to send HTTP requests effortlessly in our programs, making it an invaluable tool in the realm of web development and API integration.

Setting Up the Environment

To make HTTP requests in C++, we use the httplib library, a user-friendly and powerful library for handling HTTP requests. It is a header-only library, meaning you only need to include the header file to start using it. Additionally, we will utilize the nlohmann::json library for parsing JSON data.

Downloading and Installing Libraries:

  • httplib:

    • Being a header-only library, you can directly download the httplib.h file:
      • Run wget https://raw.githubusercontent.com/yhirose/cpp-httplib/master/httplib.h -O httplib.h to download it directly into your project directory.
  • nlohmann::json:

    • Linux (using apt):
      • Run sudo apt install nlohmann-json3-dev to install the development package.
    • Windows/Mac:
      • Download the json.hpp file from the GitHub repository and include it in your project directory.
      • Alternatively, use a package manager like vcpkg: Run vcpkg install nlohmann-json.

Once you have the libraries installed, include them in your C++ code:

With this setup, you'll be equipped to automate requests. Note that in the CodeSignal IDE environment, these libraries are already pre-configured, allowing you to focus solely on learning and practicing HTTP requests without worrying about the setup process.

Defining the Base URL

When interacting with an API, it's helpful to define a base URL for the service you're communicating with. This makes your code more modular and easy to maintain, allowing you to change the root of your API URL in one place without modifying each request:

By setting a base URL, we can easily access different endpoints within the API, making our code cleaner and more adaptable. APIs often run on specific ports to separate different services or applications on the same server. In local development, "localhost" typically refers to the local loopback address (127.0.0.1). However, the API server must be listening on the specified port for successful communication. While the default HTTP and HTTPS ports are 80 and 443 respectively, many development APIs use custom ports, such as 8000 in this case. It's crucial to ensure that the API server is running on the correct port before making requests, as using an incorrect port will lead to connection failures.

Performing a Basic GET Request

Let's dive into the process of fetching data from an API using C++. Our goal is to retrieve a list of to-do items from the /todos endpoint using the GET method.

First, we create an HTTP client object using httplib::Client, which takes two parameters:

  • base_url: A string (const char*) representing the host name or IP address of the server (in our case, "localhost")
  • port: An integer specifying the port number where the server is listening (in our case, 8000)

Next, we send a GET request to the "/todos" endpoint using the client. The response is stored in the res variable, which contains all information returned by the server.

We then print a header text to indicate we're about to show the raw response.

Finally, we check if the request was successful. If res exists (not null), it prints the response body (the actual data). If the request failed (res is null), it prints an error message and exits the program with code 1.

By using the client.Get() method, we send a GET request to the constructed full URL. The response from the server, stored in res, is then printed. You'll see the raw JSON response from the server:

Handling Successful Requests (Status Code: 200)

To determine the outcome of an HTTP request, we check the status code returned by the server. When the server responds with a status code of 200, it signifies a successful interaction, meaning the server has correctly processed the request and returned the expected data. In such cases, we can parse the body in the desired format, which is JSON in our case, using the nlohmann::json library. This allows us to access and display each to-do item.

Here is an example of what you might see when the request is successful:

By leveraging the nlohmann::json library, we can efficiently extract and work with the data returned by the server, making our programs more intuitive and powerful.

Note: While a status code of 200 indicates success, it does not always guarantee that the response contains the expected data. Some APIs may return an empty array ([]) when no records are found or a subset of records due to pagination. In such cases, make sure to implement corresponding conditional checks.

Handling Bad Requests (Status Code: 400)

Errors can happen on either the client or server side, so it's important to handle them properly. A 400 status code means there was a mistake in the request, often due to incorrect syntax from the client side. To understand these errors better, you can print the response body, which provides more details about what went wrong.

Handling Unauthorized Requests (Status Code: 401)

A 401 status code indicates an unauthorized request, often due to missing or invalid credentials. This situation requires the user to address authentication problems to proceed.

Handling Not Found Errors (Status Code: 404)

When encountering a 404 status code, it means the requested resource is not found, often pointing to a missing resource or incorrect endpoint.

Handling Internal Server Errors (Status Code: 500)

A 500 status code reflects an internal server error, indicating the server encountered an unexpected situation. Such cases usually require investigation on the server side to resolve the issue.

Handling Unexpected Status Codes

For responses falling outside the common codes, a generic approach captures these cases, ensuring all responses are analyzed for potential issues.

By handling these diverse status codes, we ensure robust API interactions and a better understanding of the server's communication.

Conclusion, Key Takeaways, and Next Steps

In this lesson, we've explored the powerful capability of C++'s httplib library to make GET requests to an API. We've seen how to retrieve and handle responses effectively, interpreting HTTP status codes to understand the server's communication. This knowledge is crucial for creating reliable interactions with APIs. As you move on to the practice exercises, focus on experimenting with the code snippets and handling various status codes to solidify your understanding. In future lessons, we will build on this foundation, unlocking the potential to perform more complex tasks like updating and manipulating API data. Keep up the great work as you advance through the course!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal