http-client-rest-api-nanoframework

Cliente HTTP en nanoFramework: consumir APIs REST

  • 4 min

Un cliente HTTP es el código que permite a nuestro dispositivo hacer peticiones a servidores web y APIs.

Ya tenemos Wi-Fi y ya tenemos la hora exacta. Ahora toca navegar.

Obviamente, nuestro microcontrolador no va a abrir YouTube, pero sí necesita comportarse como un navegador web: necesita enviar solicitudes (Requests) a servidores y procesar sus respuestas (Responses).

En el mundo del IoT, el estándar para esto es usar el protocolo HTTP/HTTPS contra APIs REST.

  • GET: “Oye servidor, dame información” (Ej. ¿Qué tiempo hace?).
  • POST: “Oye servidor, toma estos datos” (Ej. Aquí tienes la temperatura de mi salón).

En esta entrada aprenderemos a usar HttpClient, cuya API resulta familiar si ya has trabajado con .NET de escritorio.

Para este tutorial necesitas instalar el paquete NuGet: nanoFramework.System.Net.Http.Client

El ciclo petición-respuesta

Antes de tirar código, visualicemos qué ocurre.

  1. Client (ESP32): Prepara un paquete con una URL, unos encabezados (Headers) y, opcionalmente, un cuerpo (Body).
  2. Network: Viaja por Internet.
  3. Server: Procesa la petición y devuelve un código de estado (200 OK, 404 Not Found, etc.) y un contenido.

Preparar HttpClient

La clase principal es HttpClient. Conviene reutilizar una instancia mientras tenga sentido en el ciclo de vida del dispositivo y liberarla con Dispose cuando ya no vaya a utilizarse.

Lo esencial es configurar las opciones SSL si vamos a usar HTTPS (que hoy en día es el 99% de las veces).

using System;
using System.Diagnostics;
using System.Net.Http; // <--- Espacio de nombres clave
using System.Threading;

// ... dentro de tu método

// Opción básica (valida certificados estándar que tenga el firmware)
HttpClient client = new HttpClient();

// Opción avanzada (si necesitas certificados específicos, se configuran en HttpMessageHandler)
Copied!

Petición GET: leer información

Vamos a hacer una petición sencilla a una API pública de prueba. Usaremos httpbin.org o jsonplaceholder.typicode.com, que son servicios gratuitos para probar clientes HTTP.

El flujo es: GetAsync -> Esperar respuesta -> Leer contenido.

public static void RealizarPeticionGET()
{
    try
    {
        // 1. Crear el cliente
        using (HttpClient client = new HttpClient())
        {
            // 2. Definir la URL
            string url = "https://jsonplaceholder.typicode.com/todos/1";
            Debug.WriteLine($"Realizando GET a: {url}");

            // 3. Ejecutar la petición (síncrona o asíncrona)
            // En nanoFramework, GetAsync devuelve un HttpResponseMessage
            HttpResponseMessage response = client.Get(url);

            // 4. Verificar el código de estado (200 OK)
            response.EnsureSuccessStatusCode(); 

            // 5. Leer el contenido del cuerpo
            string responseBody = response.Content.ReadAsString();

            Debug.WriteLine("Respuesta recibida:");
            Debug.WriteLine(responseBody);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Error en GET: {ex.Message}");
    }
}
Copied!

Si todo va bien, verás en la consola un JSON como este: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }

Fíjate en el bloque using (...). Es fundamental. Al terminar el bloque, se llama a Dispose(), lo que cierra la conexión TCP y libera la valiosa memoria RAM del ESP32.

Petición POST: enviar datos

Ahora vamos a simular que somos un sensor enviando datos a la nube. Para ello usamos el verbo POST.

La diferencia principal es que ahora debemos enviar un Cuerpo (Body) y especificar qué tipo de contenido es (normalmente JSON).

Como aún no hemos visto la librería de JSON (próximo artículo), construiremos el JSON manualmente como un String.

public static void RealizarPeticionPOST()
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            string url = "https://httpbin.org/post";

            // 1. Preparamos los datos (JSON manual)
            string jsonManual = "{ \"sensor\": \"temp_01\", \"valor\": 24.5 }";

            // 2. Empaquetamos el contenido
            // StringContent(contenido, codificación, tipo-mime)
            StringContent content = new StringContent(jsonManual, System.Text.Encoding.UTF8, "application/json");

            Debug.WriteLine("Enviando datos...");

            // 3. Ejecutar POST
            HttpResponseMessage response = client.Post(url, content);

            // 4. Verificar respuesta
            if (response.IsSuccessStatusCode)
            {
                Debug.WriteLine("¡Datos enviados correctamente!");
                string serverResponse = response.Content.ReadAsString();
                Debug.WriteLine(serverResponse);
            }
            else
            {
                Debug.WriteLine($"Error del servidor: {response.StatusCode}");
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Excepción en POST: {ex.Message}");
    }
}
Copied!

HTTPS y Certificados CA

Una nota técnica importante. Cuando haces una petición https://..., nanoFramework comprueba el certificado del servidor.

Para que esto funcione, el ESP32 debe tener almacenado el Certificado Raíz (Root CA) de la autoridad que firmó el certificado del servidor (ej. DigiCert, Let’s Encrypt).

El dispositivo debe disponer de la CA raíz adecuada, ya sea en el almacén de certificados o proporcionada a la conexión. No des por hecho que cualquier servicio funcionará con la imagen instalada: comprueba la cadena concreta y actualiza sus certificados cuando corresponda.

Recuerda el NTP: Si el código anterior falla con una excepción de seguridad, revisa la lección anterior. Sin la hora sincronizada, HTTPS nunca funcionará.

Cabeceras de autenticación

Muchas APIs requieren una clave de API (API Key) o un Token en las cabeceras. Añadirlos es muy fácil:

client.DefaultRequestHeaders.Add("Authorization", "Bearer MI_TOKEN_SECRETO");
client.DefaultRequestHeaders.Add("X-Api-Key", "123456789");
Copied!