# D01 - Esempio programma C - API HTTP REST libmicrohttpd

Esempio pratico e funzionante di programma in C che espone una <span style="font-family: 'courier new', courier, monospace;">API HTTP REST</span> (es. `/hello`) usando una libreria leggera e molto usata: <span style="font-family: 'courier new', courier, monospace;">libmicrohttpd</span>.

È ideale per:

- servizi REST semplici
- API interne di sistema
- embedded / IoT
- interfaccia con script o sistemi esterni

##### <span style="font-size: 20px;">🚀 **Esempio completo: API in C (GET /hello)**</span>

📌<span style="font-size: 16px;"> **Requisiti**</span>

Installa la libreria:

<span style="font-family: 'courier new', courier, monospace;">sudo apt-get install libmicrohttpd-dev</span>

📄 **<span style="font-size: 16px;">api\_server.c</span>**

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;string.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;stdlib.h&gt;</span>

<span style="font-family: 'courier new', courier, monospace;">\#define PORT 8080</span>

<span style="font-family: 'courier new', courier, monospace;">// Funzione che gestisce le richieste HTTP</span>  
<span style="font-family: 'courier new', courier, monospace;">static int answer\_to\_connection(</span>  
<span style="font-family: 'courier new', courier, monospace;"> void \*cls,</span>  
<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Connection \*connection,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*url,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*method,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*version,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*upload\_data,</span>  
<span style="font-family: 'courier new', courier, monospace;"> size\_t \*upload\_data\_size,</span>  
<span style="font-family: 'courier new', courier, monospace;"> void \*\*con\_cls)</span>  
<span style="font-family: 'courier new', courier, monospace;">{</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*response\_msg;</span>

<span style="font-family: 'courier new', courier, monospace;"> if (strcmp(url, "/hello") == 0 &amp;&amp; strcmp(method, "GET") == 0) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> response\_msg = "{\\"message\\": \\"Hello from API in C!\\"}";</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>  
<span style="font-family: 'courier new', courier, monospace;"> else {</span>  
<span style="font-family: 'courier new', courier, monospace;"> response\_msg = "{\\"error\\": \\"Endpoint not found\\"}";</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>

<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Response \*response;</span>  
<span style="font-family: 'courier new', courier, monospace;"> int ret;</span>

<span style="font-family: 'courier new', courier, monospace;"> response = MHD\_create\_response\_from\_buffer(</span>  
<span style="font-family: 'courier new', courier, monospace;"> strlen(response\_msg),</span>  
<span style="font-family: 'courier new', courier, monospace;"> (void\*) response\_msg,</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_RESPMEM\_PERSISTENT);</span>

<span style="font-family: 'courier new', courier, monospace;"> MHD\_add\_response\_header(response, "Content-Type", "application/json");</span>  
<span style="font-family: 'courier new', courier, monospace;"> ret = MHD\_queue\_response(connection, MHD\_HTTP\_OK, response);</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_destroy\_response(response);</span>

<span style="font-family: 'courier new', courier, monospace;"> return ret;</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

<span style="font-family: 'courier new', courier, monospace;">int main() {</span>  
<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Daemon \*daemon;</span>

<span style="font-family: 'courier new', courier, monospace;"> daemon = MHD\_start\_daemon(</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_USE\_INTERNAL\_POLLING\_THREAD, PORT, NULL, NULL,</span>  
<span style="font-family: 'courier new', courier, monospace;"> &amp;answer\_to\_connection, NULL, MHD\_OPTION\_END);</span>

<span style="font-family: 'courier new', courier, monospace;"> if (daemon == NULL) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> fprintf(stderr, "Error starting server\\n");</span>  
<span style="font-family: 'courier new', courier, monospace;"> return 1;</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>

<span style="font-family: 'courier new', courier, monospace;"> printf("Server running on port %d\\n", PORT);</span>  
<span style="font-family: 'courier new', courier, monospace;"> printf("Try: curl http://localhost:%d/hello\\n", PORT);</span>

<span style="font-family: 'courier new', courier, monospace;"> getchar(); // Ferma il server quando premi INVIO</span>

<span style="font-family: 'courier new', courier, monospace;"> MHD\_stop\_daemon(daemon);</span>  
<span style="font-family: 'courier new', courier, monospace;"> return 0;</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

---

🔧 <span style="font-size: 16px;">**Compilazione**</span>

<span style="font-family: 'courier new', courier, monospace;">gcc api\_server.c -o api\_server -lmicrohttpd</span>

▶️ <span style="font-size: 16px;">**Esecuzione**</span>

<span style="font-family: 'courier new', courier, monospace;">./api\_server</span>

🧪 <span style="font-size: 16px;">**Test con curl**</span>

curl [http://localhost:8080/hello](http://localhost:8080/hello)

*Output:*

<span style="font-family: 'courier new', courier, monospace;">{"message": "Hello from API in C!"}</span>

---

<span style="font-size: 16px;">📁 **Struttura del Progetto**</span>

<span style="font-family: 'courier new', courier, monospace;">rest\_api\_c/</span>  
<span style="font-family: 'courier new', courier, monospace;">├── src/</span>  
<span style="font-family: 'courier new', courier, monospace;">│ ├── api\_server.c</span>  
<span style="font-family: 'courier new', courier, monospace;">│ ├── router.c</span>  
<span style="font-family: 'courier new', courier, monospace;">│ ├── router.h</span>  
<span style="font-family: 'courier new', courier, monospace;">│ └── utils.c</span>  
<span style="font-family: 'courier new', courier, monospace;">├── include/</span>  
<span style="font-family: 'courier new', courier, monospace;">│ ├── router.h</span>  
<span style="font-family: 'courier new', courier, monospace;">│ └── utils.h</span>  
<span style="font-family: 'courier new', courier, monospace;">├── Makefile</span>  
<span style="font-family: 'courier new', courier, monospace;">└── config.json (esempio)</span>

---

**📌 **1. src/api\_server.c** — Avvio server REST**

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;stdio.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;stdlib.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;string.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include "router.h"</span>

<span style="font-family: 'courier new', courier, monospace;">\#define PORT 8080</span>

<span style="font-family: 'courier new', courier, monospace;">static int answer\_to\_connection(</span>  
<span style="font-family: 'courier new', courier, monospace;"> void \*cls,</span>  
<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Connection \*connection,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*url,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*method,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*version,</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*upload\_data,</span>  
<span style="font-family: 'courier new', courier, monospace;"> size\_t \*upload\_data\_size,</span>  
<span style="font-family: 'courier new', courier, monospace;"> void \*\*con\_cls)</span>  
<span style="font-family: 'courier new', courier, monospace;">{</span>  
<span style="font-family: 'courier new', courier, monospace;"> return route\_request(connection, url, method);</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

<span style="font-family: 'courier new', courier, monospace;">int main() {</span>  
<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Daemon \*daemon;</span>

<span style="font-family: 'courier new', courier, monospace;"> daemon = MHD\_start\_daemon(</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_USE\_INTERNAL\_POLLING\_THREAD, PORT, NULL, NULL,</span>  
<span style="font-family: 'courier new', courier, monospace;"> &amp;answer\_to\_connection, NULL, MHD\_OPTION\_END);</span>

<span style="font-family: 'courier new', courier, monospace;"> if (daemon == NULL) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> fprintf(stderr, "Errore avvio server\\n");</span>  
<span style="font-family: 'courier new', courier, monospace;"> return 1;</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>

<span style="font-family: 'courier new', courier, monospace;"> printf("Server REST avviato su porta %d\\n", PORT);</span>  
<span style="font-family: 'courier new', courier, monospace;"> printf("Esempio: curl http://localhost:%d/hello\\n", PORT);</span>

<span style="font-family: 'courier new', courier, monospace;"> getchar(); // fermare server con INVIO</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_stop\_daemon(daemon);</span>  
<span style="font-family: 'courier new', courier, monospace;"> return 0;</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

---

<span style="font-size: 16px;">**📌 **2. src/router.c** — Gestione endpoint REST**</span>

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;string.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;stdio.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include "router.h"</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include "utils.h"</span>

<span style="font-family: 'courier new', courier, monospace;">int route\_request(struct MHD\_Connection \*connection, const char \*url, const char \*method) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> const char \*response\_msg;</span>

<span style="font-family: 'courier new', courier, monospace;"> if (strcmp(url, "/hello") == 0 &amp;&amp; strcmp(method, "GET") == 0) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> response\_msg = "{\\"message\\": \\"Hello from REST API C\\"}";</span>  
<span style="font-family: 'courier new', courier, monospace;"> return send\_response(connection, response\_msg, MHD\_HTTP\_OK);</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>  
<span style="font-family: 'courier new', courier, monospace;"> else if (strcmp(url, "/status") == 0 &amp;&amp; strcmp(method, "GET") == 0) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> response\_msg = "{\\"status\\": \\"OK\\", \\"service\\": \\"running\\"}";</span>  
<span style="font-family: 'courier new', courier, monospace;"> return send\_response(connection, response\_msg, MHD\_HTTP\_OK);</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>  
<span style="font-family: 'courier new', courier, monospace;"> else {</span>  
<span style="font-family: 'courier new', courier, monospace;"> response\_msg = "{\\"error\\": \\"Not Found\\"}";</span>  
<span style="font-family: 'courier new', courier, monospace;"> return send\_response(connection, response\_msg, MHD\_HTTP\_NOT\_FOUND);</span>  
<span style="font-family: 'courier new', courier, monospace;"> }</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

---

<span style="font-size: 16px;">**📌 **3. include/router.h****</span>

<span style="font-family: 'courier new', courier, monospace;">\#ifndef ROUTER\_H</span>  
<span style="font-family: 'courier new', courier, monospace;">\#define ROUTER\_H</span>

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>

<span style="font-family: 'courier new', courier, monospace;">int route\_request(struct MHD\_Connection \*connection, const char \*url, const char \*method);</span>

<span style="font-family: 'courier new', courier, monospace;">\#endif</span>

---

**📌 **4. src/utils.c** — Funzioni per risposte HTTP**

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include &lt;string.h&gt;</span>  
<span style="font-family: 'courier new', courier, monospace;">\#include "utils.h"</span>

<span style="font-family: 'courier new', courier, monospace;">int send\_response(struct MHD\_Connection \*connection, const char \*msg, int status\_code) {</span>  
<span style="font-family: 'courier new', courier, monospace;"> struct MHD\_Response \*response = MHD\_create\_response\_from\_buffer(</span>  
<span style="font-family: 'courier new', courier, monospace;"> strlen(msg), (void\*) msg, MHD\_RESPMEM\_PERSISTENT);</span>

<span style="font-family: 'courier new', courier, monospace;"> MHD\_add\_response\_header(response, "Content-Type", "application/json");</span>

<span style="font-family: 'courier new', courier, monospace;"> int ret = MHD\_queue\_response(connection, status\_code, response);</span>  
<span style="font-family: 'courier new', courier, monospace;"> MHD\_destroy\_response(response);</span>  
<span style="font-family: 'courier new', courier, monospace;"> return ret;</span>  
<span style="font-family: 'courier new', courier, monospace;">}</span>

---

<span style="font-size: 16px;">**📌 **5. include/utils.h****</span>

<span style="font-family: 'courier new', courier, monospace;">\#ifndef UTILS\_H</span>  
<span style="font-family: 'courier new', courier, monospace;">\#define UTILS\_H</span>

<span style="font-family: 'courier new', courier, monospace;">\#include &lt;microhttpd.h&gt;</span>

<span style="font-family: 'courier new', courier, monospace;">int send\_response(struct MHD\_Connection \*connection, const char \*msg, int status\_code);</span>

<span style="font-family: 'courier new', courier, monospace;">\#endif</span>

---

****📌 **6. Makefile******

<div id="bkmrk-cc-%3D-gcc"><span style="font-family: 'courier new', courier, monospace;">CC = gcc</span></div><div id="bkmrk-cflags-%3D--wall--iinc"><span style="font-family: 'courier new', courier, monospace;">CFLAGS = -Wall -Iinclude</span></div><div id="bkmrk-libs-%3D--lmicrohttpd"><span style="font-family: 'courier new', courier, monospace;">LIBS = -lmicrohttpd</span></div><div id="bkmrk--8">  
</div><div id="bkmrk-src-%3D-src%2Fapi_server"><span style="font-family: 'courier new', courier, monospace;">SRC = src/api\_server.c src/router.c src/utils.c</span></div><div id="bkmrk-obj-%3D-%24%28src%3A.c%3D.o%29"><span style="font-family: 'courier new', courier, monospace;">OBJ = $(SRC:.c=.o)</span></div><div id="bkmrk--9">  
</div><div id="bkmrk-target-%3D-rest_api"><span style="font-family: 'courier new', courier, monospace;">TARGET = rest\_api</span></div><div id="bkmrk--10">  
</div><div id="bkmrk-all%3A-%24%28target%29"><span style="font-family: 'courier new', courier, monospace;">all: $(TARGET)</span></div><div id="bkmrk--11">  
</div><div id="bkmrk-%24%28target%29%3A-%24%28obj%29"><span style="font-family: 'courier new', courier, monospace;">$(TARGET): $(OBJ)</span></div><div id="bkmrk-%24%28cc%29-%24%28obj%29--o-%24%28ta"><span style="font-family: 'courier new', courier, monospace;">$(CC) $(OBJ) -o $(TARGET) $(LIBS)</span></div><div id="bkmrk--12">  
</div><div id="bkmrk-clean%3A"><span style="font-family: 'courier new', courier, monospace;">clean:</span></div><div id="bkmrk-rm--f-%24%28obj%29-%24%28targe"><span style="font-family: 'courier new', courier, monospace;">rm -f $(OBJ) $(TARGET)</span></div>---

<span style="font-size: 16px;">🧪 **Test API**</span>

*Compila ed esegui*:

<span style="font-size: 14px;"><span style="font-family: 'courier new', courier, monospace;">make</span>  
<span style="font-family: 'courier new', courier, monospace;">./rest\_api</span>  
</span>

*<span style="font-size: 14px;">Test via curl:</span>*

<span style="font-size: 14px;"><span style="font-family: 'courier new', courier, monospace;">curl http://localhost:8080/hello</span>  
<span style="font-family: 'courier new', courier, monospace;">curl [http://localhost:8080/status](http://localhost:8080/status)</span>  
</span>

*<span style="font-size: 14px;">Output:</span>*

<span style="font-size: 14px;"><span style="font-family: 'courier new', courier, monospace;">{"message": "Hello from REST API C"}</span>  
<span style="font-family: 'courier new', courier, monospace;">{"status": "OK", "service": "running"}</span>  
</span>

---

Tutorials:

[https://www.gnu.org/software/libmicrohttpd/tutorial.html#Hello-browser-example](https://www.gnu.org/software/libmicrohttpd/tutorial.html#Hello-browser-example)

[https://docs.oracle.com/cd/E88353\_01/html/E37842/libmicrohttpd-3lib.html](https://docs.oracle.com/cd/E88353_01/html/E37842/libmicrohttpd-3lib.html)