Building a RESTful API with Ulfius in C
Creating a RESTful API in C is a rewarding experience that enhances your understanding of web technologies and the C programming language’s capabilities. This tutorial guides you through developing a simple Book CRUD API using the Ulfius framework for handling HTTP requests and the Jansson library for JSON manipulation.
Introduction
The C programming language, known for its efficiency and control, is not typically associated with web server development. However, with the right libraries, C can be an excellent choice for creating lightweight and high-performance web APIs. The Ulfius framework and Jansson library make a powerful combination for such tasks, allowing C programmers to create RESTful APIs that are both fast and flexible.
Setting Up Your Environment
Before we start coding, ensure you have the following installed on your system:
- GCC compiler
- Ulfius framework
- Jansson library
You can install Ulfius and Jansson from their respective official sources or through your operating system’s package manager.
The Book Model
Our API will manage a simple book model, which includes an ID and a name. Here’s how we define it in C:
typedef struct {
int id;
char name[256];
} Book;
Setting Up Ulfius
To set up Ulfius, we initialize an instance of the framework and specify the endpoint URLs:
#include <ulfius.h>
#define PORT 8080
int main(void) {
struct _u_instance instance;
if (ulfius_init_instance(&instance, PORT, NULL, NULL) != U_OK) {
fprintf(stderr, "Error initializing instance\n");
return 1;
}
// Endpoint declarations go here
if (ulfius_start_framework(&instance) == U_OK) {
printf("Server started on port %d\n", instance.port);
getchar(); // Wait for user input to stop the server
} else {
fprintf(stderr, "Error starting framework\n");
}
ulfius_stop_framework(&instance);
ulfius_clean_instance(&instance);
return 0;
}
Implementing CRUD Operations
Create a Book
To handle book creation, we define a POST endpoint:
int callback_create_book(const struct _u_request *request, struct _u_response *response, void *user_data) {
json_t *json_body = ulfius_get_json_body_request(request, NULL);
const char *name = json_string_value(json_object_get(json_body, "name"));
// Logic to add the book to storage
json_decref(json_body);
ulfius_set_string_body_response(response, 200, "Book created");
return U_CALLBACK_CONTINUE;
}
Then, we add the endpoint before starting the framework:
ulfius_add_endpoint_by_val(&instance, "POST", "/book", NULL, 0, &callback_create_book, NULL);
Read, Update, Delete
Following a similar structure, you can implement the remaining CRUD operations. Here’s a brief overview of how to set up these endpoints:
- Read: Implement a GET endpoint to retrieve books.
- Update: Use a PUT endpoint to update a book’s details.
- Delete: A DELETE endpoint will remove a book from the collection.
Logging
For logging, we define a simple function to log requests:
#include <time.h>
void log_request(const struct _u_request *request) {
time_t now = time(NULL);
char formatted_time[20];
strftime(formatted_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&now));
printf("[%s] Received %s request for %s\n", formatted_time, request->http_verb, request->http_url);
}
Conclusion
This tutorial has shown you how to build a basic RESTful API in C using the Ulfius framework and Jansson library. With Ulfius handling HTTP requests and Jansson managing JSON data, you can efficiently develop web APIs that leverage C’s performance advantages.
Remember, while C provides great power and efficiency, it also requires careful attention to memory management and security considerations, especially when dealing with external input. Always validate and sanitize incoming data to protect your API from potential vulnerabilities.
Happy coding, and may your C projects be successful and bug-free!
Full source code: https://github.com/araujo88/ulfius-test
Full documentation: https://babelouest.github.io/ulfius/