D01 - Esempio programma C - API HTTP REST libmicrohttpd
Esempio pratico e funzionante di programma in C che espone una API HTTP REST (es. /hello) usando una libreria leggera e molto usata: libmicrohttpd.
È ideale per:
-
servizi REST semplici
-
API interne di sistema
-
embedded / IoT
-
interfaccia con script o sistemi esterni
🚀 Esempio completo: API in C (GET /hello)
📌 Requisiti
Installa la libreria:
sudo apt-get install libmicrohttpd-dev
📄 api_server.c
#include <microhttpd.h>
#include <string.h>
#include <stdlib.h>
#define PORT 8080
// Funzione che gestisce le richieste HTTP
static int answer_to_connection(
void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *version,
const char *upload_data,
size_t *upload_data_size,
void **con_cls)
{
const char *response_msg;
if (strcmp(url, "/hello") == 0 && strcmp(method, "GET") == 0) {
response_msg = "{\"message\": \"Hello from API in C!\"}";
}
else {
response_msg = "{\"error\": \"Endpoint not found\"}";
}
struct MHD_Response *response;
int ret;
response = MHD_create_response_from_buffer(
strlen(response_msg),
(void*) response_msg,
MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Content-Type", "application/json");
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
return ret;
}
int main() {
struct MHD_Daemon *daemon;
daemon = MHD_start_daemon(
MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL,
&answer_to_connection, NULL, MHD_OPTION_END);
if (daemon == NULL) {
fprintf(stderr, "Error starting server\n");
return 1;
}
printf("Server running on port %d\n", PORT);
printf("Try: curl http://localhost:%d/hello\n", PORT);
getchar(); // Ferma il server quando premi INVIO
MHD_stop_daemon(daemon);
return 0;
}
🔧 Compilazione
gcc api_server.c -o api_server -lmicrohttpd
▶️ Esecuzione
./api_server
🧪 Test con curl
curl http://localhost:8080/hello
Output:
{"message": "Hello from API in C!"}
📁 Struttura del Progetto
rest_api_c/
├── src/
│ ├── api_server.c
│ ├── router.c
│ ├── router.h
│ └── utils.c
├── include/
│ ├── router.h
│ └── utils.h
├── Makefile
└── config.json (esempio)
📌 1. src/api_server.c — Avvio server REST
#include <microhttpd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "router.h"
#define PORT 8080
static int answer_to_connection(
void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *version,
const char *upload_data,
size_t *upload_data_size,
void **con_cls)
{
return route_request(connection, url, method);
}
int main() {
struct MHD_Daemon *daemon;
daemon = MHD_start_daemon(
MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL,
&answer_to_connection, NULL, MHD_OPTION_END);
if (daemon == NULL) {
fprintf(stderr, "Errore avvio server\n");
return 1;
}
printf("Server REST avviato su porta %d\n", PORT);
printf("Esempio: curl http://localhost:%d/hello\n", PORT);
getchar(); // fermare server con INVIO
MHD_stop_daemon(daemon);
return 0;
}
📌 2. src/router.c — Gestione endpoint REST
#include <microhttpd.h>
#include <string.h>
#include <stdio.h>
#include "router.h"
#include "utils.h"
int route_request(struct MHD_Connection *connection, const char *url, const char *method) {
const char *response_msg;
if (strcmp(url, "/hello") == 0 && strcmp(method, "GET") == 0) {
response_msg = "{\"message\": \"Hello from REST API C\"}";
return send_response(connection, response_msg, MHD_HTTP_OK);
}
else if (strcmp(url, "/status") == 0 && strcmp(method, "GET") == 0) {
response_msg = "{\"status\": \"OK\", \"service\": \"running\"}";
return send_response(connection, response_msg, MHD_HTTP_OK);
}
else {
response_msg = "{\"error\": \"Not Found\"}";
return send_response(connection, response_msg, MHD_HTTP_NOT_FOUND);
}
}
📌 3. include/router.h
#ifndef ROUTER_H
#define ROUTER_H
#include <microhttpd.h>
int route_request(struct MHD_Connection *connection, const char *url, const char *method);
#endif
📌 4. src/utils.c — Funzioni per risposte HTTP
#include <microhttpd.h>
#include <string.h>
#include "utils.h"
int send_response(struct MHD_Connection *connection, const char *msg, int status_code) {
struct MHD_Response *response = MHD_create_response_from_buffer(
strlen(msg), (void*) msg, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Content-Type", "application/json");
int ret = MHD_queue_response(connection, status_code, response);
MHD_destroy_response(response);
return ret;
}
📌 5. include/utils.h
#ifndef UTILS_H
#define UTILS_H
#include <microhttpd.h>
int send_response(struct MHD_Connection *connection, const char *msg, int status_code);
#endif
📌 6. Makefile
🧪 Test API
Compila ed esegui:
make
./rest_api
Test via curl:
curl http://localhost:8080/hello
curl http://localhost:8080/status
Output:
{"message": "Hello from REST API C"}
{"status": "OK", "service": "running"}
Tutorials:
https://www.gnu.org/software/libmicrohttpd/tutorial.html#Hello-browser-example
https://docs.oracle.com/cd/E88353_01/html/E37842/libmicrohttpd-3lib.html
Nessun commento