Mostrando las entradas para la consulta node ordenadas por fecha. Ordenar por relevancia Mostrar todas las entradas
Mostrando las entradas para la consulta node ordenadas por fecha. Ordenar por relevancia Mostrar todas las entradas

sábado, 4 de abril de 2026

WebAssembly con Dlang

WebAssembly es un lenguaje de bajo nivel, similar a ensamblador, diseñado para ser rápido de cargar y ejecutar en navegadores modernos. Su objetivo es permitir que aplicaciones escritas en distintos lenguajes se ejecuten en la web con velocidad casi nativa.

Los formatos que soporta son:

  • .wasm: un formato binario ejecutable. 
  •  .wat: un formato formato de texto legible.

Se complementa con JavaScript; permite invocar funciones WASM desde JS y viceversa. Y como vimos en este blog, también puedes optar por usar un lenguaje como Grain cuya compilación es directa a WASM.

¿Cuál es el objetivo de WebAssembly?

El objetivo de WebAssembly es compilar código escrito en lenguajes como Rust, C o C++ (entre otros) y transformarlo en un módulo .wasm que puede ejecutarse en navegadores o en entornos como Node.js con rendimiento cercano al nativo.

Flujo típico de trabajo con WebAssembly:

  1. Escribimos nuestro código en un lenguaje soportado (ej. Rust, C, C++, Go, AssemblyScript). 
  2. Compilamos ese código a WebAssembly y se generará un archivo .wasm. 
  3. Cargamos el módulo en tu aplicación web usando JavaScript. 
  4. Ejecutamos las funciones exportadas desde el módulo .wasm  como si fueran algo nativo.

¿Y qué con Dlang?

Dlang es un lenguaje similar al mítico y poderoso C. No solo en su sintaxis sino en su filosofía.

Dlang permite generar código WASM mediante la herramienta LDC.

Creando código WASM con Dlang

Crearemos una sencilla función llamada ``suma_wasm.d``.

extern(C): 

double suma(double a, double b) { return a + b; }

void _start() {}

Compilamos para generar el código WASM:

$ ldc2 -mtriple=wasm32-unknown-unknown-wasm -betterC suma_wasm.d

Ahora crearemos una página HTML para cargar el código WASM generado (suma_wasm.wasm).

index.html

<html>
  <head>
    <script>
      const request = new XMLHttpRequest();
      request.open('GET', 'suma_wasm.wasm');
      request.responseType = 'arraybuffer';
      request.onload = () => {
        console.log('respuesta recibida');
        const bytes = request.response;
        const importObject = {};
        WebAssembly.instantiate(bytes, importObject).then(result => {
          console.log('iniciado');
          const { exports } = result.instance;
          const r = exports.suma(33, 10.88);
          console.log('r = ' + r);
        });
      };
      request.send();
      console.log('solicitud enviada');
    </script>
  </head>
  <body>
    Código D desde WebAssembly
  </body>
</html>

Ahora ejecutaremos este comando para abrir la página web:

$ python -m http.server 8000

Abrimos un navegador en la ruta: http://localhost:8000

Salida:

solicitud enviada
respuesta recibida
iniciado
r = 43.88

WebAssembly permite que aplicaciones complejas escritas en lenguajes de alto nivel como D, C/C++, Rust, etc. se ejecuten en aplicaciones web a través de un compilado .wasm.

Imaginemos que hemos creado una aplicación para gestionar datos complejos en Rust o Java y la queremos ejecutar como una aplicación web. Con WebAssembly es posible. Se podrá compialr ese código y generar un archivo .wasm que podrá ser cargado en una página web.

Continuaremos con este tema en próximas entregas.

Enlaces:

https://dlang.org/
https://webassembly.org/
https://wiki.dlang.org/Generating_WebAssembly_with_LDC
https://alquimistadecodigo.blogspot.com/2026/04/webassembly-con-rust.html


jueves, 2 de abril de 2026

Grain, un lenguaje para WebAssembly

Grain es un lenguaje de programación funcional, moderno y de código abierto, diseñado principalmente para compilarse a WebAssembly (Wasm), lo que le permite funcionar eficientemente tanto en navegadores web como en servidores. Su objetivo es hacer accesibles las características avanzadas de los lenguajes funcionales, siendo fácil de aprender, fuertemente tipado y flexible.

¿Qué es WebAssembly?

  • Un formato de instrucciones binarias para una máquina virtual basada en pila. 
  • Diseñado como un destino de compilación portátil para lenguajes de programación, lo que permite su implementación en la web para aplicaciones cliente y servidor.

Características más importantes:

  • Eficiente y rápido. 
  • Seguro. 
  • Abierto y depurable. 
  • Parte de la plataforma web abierta.

Grain es una alternativa directa a la compilación de código wasm. Si quieres usar lenguajes como C o C++ tendrías que usar https://emscripten.org/. Si quieres usar Python podrás elegir entre https://pyodide.org/en/stable/, https://github.com/wasmerio/py2wasm o https://pygame-web.github.io/. Entre otras alternativas dependiende el lenguaje de programación (Java, C#, Kotlin, Scala, Go, etc.).

Grain posee sus propias herramientas para compilar código y su línea de comandos.

Lo puedes instalar en sistemas Mac OS, Linux y Windows.  Si no deseas instalarlo, puede visitar este sitio y probar el lenguaje: https://grain-lang.org/try/

Otra forma de obtenerlo es con Node (V22 como mínima versión). Primero clonamos el repositorio:

$ git clone https://github.com/grain-lang/grain
$ cd grain

Una vez clonado el repositorio y ubicandonos en el directorio ejecutamose estos comandos para su construcción:

$ npm ci
$ npm run compiler build

Validamos la instalación:

$ grain --version

¡Tenemos instalado Grain en nuestro sistema!

Ahora demos un vistazo al lenguaje.

Al ser un lenguaje fuertemente tipado posee tipos básicos como Number, Bool, String y Char. Observemos la siguiente tabla:

Tipo Descripción Ejemplo
Number Representa números enteros o decimales. let x: Number = 42
Bool Valores booleanos: verdadero o falso. let flag: Bool = true
String Secuencia de caracteres, texto. let msg: String = "Hola Grain"
Char Un solo carácter Unicode. let letter: Char = 'A'

Grain usa la palabra clave ``let`` para introducir nuevos valores con un nombre determinado, a los que se les llama enlaces:

module Main

let numero = 42
let bandera = true
let saludo = "Bienvenido a Grain!"
and letra = 'A'

Hola mundo en Grain

Probemos el clásico programa "Hola, mundo" en este lenguaje.

holamundo.gr

module HolaMundo

print("Hola, mundo en Grain")

Para compilar y ejecutarlo directamente tecleamos:

$ grain holamundo.gr

Con pasos separados:

$ grain compile holamundo.gr 
# Te creará un archivo `holamundo.gr.wasm`
$ grain run holamundo.gr.wasm

Notar que te crea un archivo WASM ejecutable.

Continuaremos con este tema en próximas entregas.

Enlaces:

https://grain-lang.org/
https://webassembly.org/
https://alquimistadecodigo.blogspot.com/2026/04/webassembly-hola-mundo-en-python-con.html




viernes, 6 de marzo de 2026

WebSockets: un canal permanente para enviar y recibir datos

Los WebSockets son un protocolo que permite comunicación bidireccional en tiempo real entre cliente y servidor, a diferencia de HTTP que funciona en modo solicitud-respuesta.

Es como un canal permanente, donde ambos lados (cliente y servidor) pueden enviar datos en cualquier momento.

Son útiles en cualquier escenario donde se requiera interacción instantánea:

  • Chats y mensajería: WhatsApp Web, Slack, Discord. 
  • Juegos online: sincronización de movimientos en tiempo real. 
  • Colaboración en documentos: Google Docs, Notion, donde ves cambios de otros usuarios al instante.
  • Notificaciones en vivo: alertas de bolsa, actualizaciones deportivas, sistemas de monitoreo. 
  • Aplicaciones financieras: transmisión de precios de criptomonedas o acciones en tiempo real. 
  • IoT y dashboards: dispositivos que envían datos continuamente a una interfaz web .

Entre las ventajas principales encontramos:

  • Baja latencia: no hay que abrir y cerrar conexiones constantemente. 
  • Menor consumo de recursos: menos overhead que múltiples peticiones HTTP. 
  • Escalabilidad: ideal para aplicaciones con miles de usuarios conectados simultáneamente.  
  • Flexibilidad: permite enviar datos en ambos sentidos (cliente ↔ servidor).

Entre los riesgos y consideraciones a tomar tenemos:

  • Seguridad: al ser persistentes, requieren cifrado (wss://) para evitar ataques de interceptación. 
  • Escalabilidad: manejar miles de conexiones simultáneas exige servidores optimizados. 
  • Compatibilidad: aunque ampliamente soportados, algunos entornos antiguos pueden no tener soporte completo.

WebSockets

Iniciemos pues con los WebSockets. Haremos un sencillo ejemplo. Para ello necesitamos:

  • Tener Node instalado en nuestras máquinas. 
  • Tener conocimiento de Javascript y Node. 
  • Instalar Express y Socket.IO

¿Qué haremos? Una aplicación que nos muestre un ejemplo del uso de WebSockets, con ayuda de JS y Node.

1. Crearemos un directorio y nos ubicaremos en el:

$ mkdir websocket-demo
$ cd websocket-demo

2. Una vez dentro del directorio, crearemos un proyecto Node:

$ npm init -y

Esto nos generará el proyecto Node.

3. Instalar las dependencias (Express y Socket.IO) con ayuda de la herramienta ``npm``:

$ npm install express socket.io

Podemos validar la descarga con este comando:

$ npm list

Salida:

+-- express@5.2.1
`-- socket.io@4.8.3

4. Creando un servidor que escuche ``server.js``:

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = new Server(server);

app.use(express.static('public'));

io.on('connection', (socket) => {
  console.log('Un usuario se conectó');

  socket.on('chat message', (msg) => {
    console.log('Mensaje recibido: ' + msg);
    io.emit('chat message', msg);
  });

  socket.on('disconnect', () => {
    console.log('Un usuario se desconectó');
  });
});

server.listen(3000, () => {
  console.log('Servidor escuchando en http://localhost:3000');
});

5. Crearemos un cliente para hacer petciones al servidor:

public\index.html

<!DOCTYPE html>
<html>
<head>
  <title>Chat con Socket.IO</title>
</head>
<body>
  <h1>Chat sencillo</h1>
  <ul id="mensajes"></ul>
  <form id="form">
    <input id="input" autocomplete="off" /><button>Enviar</button>
  </form>
  <script src="/socket.io/socket.io.js"></script>
  <script>
    const socket = io();

    const form = document.getElementById('form');
    const input = document.getElementById('input');
    const messages = document.getElementById('mensajes');
form.addEventListener('submit', (e) => { e.preventDefault(); if (input.value) { socket.emit('chat message', input.value); input.value = ''; } }); socket.on('chat message', (msg) => { const item = document.createElement('li'); item.textContent = msg; messages.appendChild(item); }); </script> </body> </html>

6. Ejecutamos la aplicación:

$ node server.js

Si todo va bien veremos este mensaje:

Servidor escuchando en http://localhost:3000

Abrimos un navegador en la ruta: http://localhost:3000/

Veremos lo siguiente:

Mandamos un mensaje y obtendremos una respuesta:

¡Hemos creado nuestra primera aplicación con WebSockets!

Continuaremos con estos temas en próximas entregas.

Enlaces:

https://en.wikipedia.org/wiki/WebSocket
https://socket.io/
https://expressjs.com/

lunes, 2 de febrero de 2026

OpenCode: un agente para escribir código

OpenCode es una alternativa Open Source a herramientas como Claude Code.

Está disponible como interfaz de terminal, aplicación de escritorio o extensión de IDE. Sirve para acelerar el desarrollo de software al generar, analizar, editar y corregir código. Permite multisesiones, se conecta con Github Copilot, entre otras cosas más.

Puedes usarlo a la par con ChatGPT Plus/Pro, Github Copilot, etc. mediante una subscripción. Aunque no necesitas necesariamente una subscripción para usar OpenCode. Además te permite personalizarlo.

En pocas palabras, con OpenCode podrás crear código de manera fácil desde una terminal.

¿Cómo instalo OpenCode?

Requisitos:

  • Emulador de terminal moderno: WezTerm, Alacritty, Ghostty o Kitty. 
  • Claves API: Debes tener credenciales de los proveedores de LLM que quieras usar (ej. OpenAI, Anthropic, Google Gemini). 
  • Sistema operativo compatible: macOS, Linux o Windows (con WSL recomendado).

Existen varias formas de hacerlo.

En entornos Linux:

$ curl -fsSL https://opencode.ai/install | bash

Con Node JS:

# npm
$ npm install -g opencode-ai

# bun
$ bun install -g opencode-ai

# pnpm
$ pnpm install -g opencode-ai

# yarn
$ yarn global add opencode-ai

En entornos Mac OS:

$ brew install anomalyco/tap/opencode

Con un instalador .exe (Windows):

https://opencode.ai/download

Verificamos la instalación:

$ opencode --version

OpenCode necesita conectarse a modelos de IA. Puedes configurar tus credenciales en el archivo de configuración:

$ opencode config set 
$ openai_api_key=TU_API_KEY
$ opencode config set anthropic_api_key=TU_API_KEY
$ opencode config set gemini_api_key=TU_API_KEY

Seleccionamos un modelo por defecto:

$ opencode config set default_model=openai:gpt-4

Podemos abrirlo de manera interactiva:

$ opencode 

También escribiendo un prompt de manera directa:

$ opencode "Escribe un script en Python que calcule la serie de Fibonacci"

Conclusiones:

OpenCode (y herramientas similares) ayudará a los programadores a hacer su trabajo más rápido y a otros les hará creer que son programadores sin serlo (como lo hizo Visual Basic en su momento).

La I.A. ya llegó. Lo que imaginabamos o veíamos en series o películas de ciencia ficción se ha vuelto una realidad. El programador pronto pasará a ser un espectador (lo queramos o no) que solicita X o Y cosa para que un asistente virtual nos sirva lo solicitado.

El futuro es la automatización del trabajo. No ayudar al trabajador a hacer su trabajo más rápido. No, no es el caso.

2026 mostrará la otra cara de la I.A. una que casi nadie quiere ver: el desplazamiento del humano por un agente virtual.

Quien se duerma en sus laureles pronto será reemplazado. Ese es el plan a futuro. Solo un tonto no lo verá de ese modo.

Enlaces:

https://opencode.ai/
https://lapascalinaatomica.blogspot.com/2026/02/fortran-oberon-y-pascal-frente-la-ia.html

jueves, 25 de diciembre de 2025

Websharper

Websharper, según la documentación oficial es: un framework y un conjunto de herramientas para desarrollar aplicaciones web/móviles y servicios web íntegramente en C# o F# (o una combinación de ambos lenguajes) con comunicación cliente-servidor y navegación web fuertemente tipadas.

Características principales:

Veremos las sus características principales.

  • Sitelets: funcionalidad del lado del servidor. 
  • Compilador de JavaScript y abstracciones del lado del cliente. 
  • Facilidades de interacción cliente-servidor. 
  • Funciones adicionales.

Empezando con Websharper

Por default se usa C#, veamos un ejemplo paso a paso.

1. Creamos un directorio y nos ubicamos en el:

$ mkdir proyecto-websharper
$ cd proyecto-websharper

2. Instalamos los templates de WebSharper:

$ dotnet new -i WebSharper.Templates

3. Creamos un proyecto WebSharper:

$ dotnet new websharper-web

4. Ejecutamos la aplicación:

$ dotnet run

Abrimos el navegador en la ruta: http://localhost:5000

Con esto hemos creado nuestra primera aplicación con WebSharper.

Ahora miremos el contenido del proyecto:

Como se puede observar hay directorios que llaman la atención, describiremos las carpetas:

  • bin: Carpeta estándar de .NET donde se colocan los archivos compilados finales (DLLs, ejecutables, etc.) después de construir el proyecto. En proyectos WebSharper, también puede contener subcarpetas con archivos generados para despliegue (como HTML/JS en versiones antiguas). 
  • Generated: Carpeta generada automáticamente por WebSharper. Contiene código JavaScript (y posiblemente otros artefactos) traducido desde el código C# marcado con atributos como [JavaScript]. Este código es el resultado de la compilación client-side de WebSharper. 
  • node_modules: Carpeta creada por npm (Node.js package manager). Contiene todas las dependencias JavaScript externas instaladas vía package.json. En proyectos WebSharper modernos, se usa para herramientas de bundling como Vite o esbuild, y para librerías frontend. 
  • obj: Carpeta estándar de compilación .NET. Almacena archivos intermedios temporales durante el proceso de build (como objetos compilados, recursos embebidos, etc.). No se debe modificar manualmente ni incluir en control de versiones. 
  • wwwroot: Carpeta raíz para archivos estáticos en proyectos web .NET (como ASP.NET Core). Aquí se colocan los archivos que se sirven directamente al navegador: HTML, CSS, JS bundlado, imágenes, etc. En WebSharper, el output final del cliente (JS generados, bundles) suele configurarse para ir aquí (a menudo vía wsconfig.json con "outputDir": "wwwroot").

Estas carpetas combinan elementos estándar de proyectos .NET/ASP.NET Core con específicas de WebSharper (como Generated) y modernas herramientas frontend (como node_modules y configuración para bundlers como Vite/esbuild, visibles en archivos como vite.config.js y esbuild.config.mjs).

Ahora miremos los achivos:

  • proyecto-websharper.csproj: Archivo de proyecto principal de .NET (formato SDK-style). Define la configuración del proyecto: tipo de salida (generalmente una aplicación web ASP.NET Core), referencias a paquetes NuGet (como WebSharper, WebSharper.CSharp, etc.), propiedades de compilación y opciones específicas de WebSharper (por ejemplo, vía propiedades como o referencias a targets). Es esencial para que dotnet build o Visual Studio compile el proyecto correctamente. 
  • appsettings.json: Archivo de configuración estándar de ASP.NET Core. Contiene settings de la aplicación, como cadenas de conexión a bases de datos, opciones de logging, URLs de APIs externas o configuraciones específicas de WebSharper (por ejemplo, sección "websharper" para redirección de scripts en modo debug). Se carga en tiempo de ejecución y puede tener versiones por entorno (como appsettings.Development.json). 
  • Client.cs: Archivo de código C# que contiene la lógica client-side (lado del navegador). Aquí se escribe código marcado con atributos como [JavaScript] o [SPAEntryPoint], que WebSharper traduce automáticamente a JavaScript. Es el punto principal para definir la interfaz de usuario interactiva (UI con WebSharper.UI, eventos, etc.). 
  • esbuild.config.mjs: Archivo de configuración para esbuild (un bundler/minificador rápido de JavaScript). En proyectos WebSharper modernos, se usa para procesar el output prebundled generado por WebSharper (cuando "prebundle": true en wsconfig.json), creando un bundle final optimizado para producción (minificación, tree-shaking, etc.). 
  • Main.html: Archivo HTML principal (plantilla o index). Sirve como página base para la aplicación (SPA o sitelet). Contiene placeholders especiales de WebSharper (como
    o atributos ws-replace) donde se inyecta el contenido dinámico generado desde el lado server o client. En modo desarrollo, Vite lo sirve con hot-reload. 
  • package.json: Archivo estándar de Node.js/npm. Define las dependencias JavaScript externas (como librerías UI, polyfills o herramientas) y scripts de build (por ejemplo, "dev" para Vite, "build" para producción). WebSharper lo usa para integrar con bundlers modernos como Vite o esbuild. 
  • Remoting.cs: Archivo C# que define funciones RPC (Remote Procedure Calls). Contiene métodos marcados con [Rpc] que permiten llamar código server-side desde el client de forma segura y tipada (sin escribir AJAX manual). Es clave para la comunicación client-server en aplicaciones WebSharper. 
  • Site.cs: Archivo C# que define el sitelet (estructura de rutas y páginas de la aplicación). Usa WebSharper.Sitelets para declarar endpoints (acciones, páginas, etc.) y cómo renderizar el contenido (integrando templates como Main.html y código client). Es el núcleo de la lógica de enrutamiento server-side. 
  • Startup.cs: Archivo estándar de ASP.NET Core para configurar la aplicación. Aquí se registra el pipeline (middleware), se integra WebSharper (por ejemplo, services.AddWebSharper() o configuración de sitelets/RPC), se carga appsettings.json y se define el hosting (Kestrel, IIS, etc.). 
  • vite.config.js: Archivo de configuración para Vite (servidor de desarrollo y bundler moderno). Se usa en modo debug para hot-module-replacement (HMR), proxy de APIs y servir el proyecto rápidamente. En producción, puede delegar a esbuild. Los templates WebSharper recientes lo incluyen para un desarrollo fluido. 
  • wsconfig.json: Archivo de configuración específico de WebSharper. Define opciones del compilador como tipo de proyecto ("site", "spa", etc.), output directory (ej. "wwwroot"), prebundling, source maps, descarga de recursos remotos y más. Es crucial para personalizar cómo WebSharper genera el JavaScript.

Continuaremos con esta serie de entregas sobre .NET.

Enlaces:

https://websharper.com/

sábado, 1 de noviembre de 2025

El roadmap para ser desarrollador C#

Nota: Este post esta basado en https://www.youtube.com/watch?v=sZVqGIW6Jno

Aquí un roadmap para ser desarrollador C#.

1. Aprender C# desde la consola.

  • Aprende a usar la consola para crear proyectos, compilarlos y ejecutarlos. 
  • Conoce el lenguaje, los paradigmas que usa. Los tipos de datos, estructuras de control (if, if-else, for, while, etc.) y estructuras de datos. 
  • Entiende lo que es el paradigma orientado a objetos.
  • Crea aplicaciones de consola para aprender y poner en práctica los fundamentos. 
  • Crea aplicaciones para el manejo de archivos (abrir archivos, crearlos y borrarlos). 
  • Crea aplicaciones para acceder a BD (el clásico CRUD). 
  • Crea aplicaciones para acceder a API's públicas.

Nota: Olvídate de aprender Visual Basic .NET a menos que tengas que trabajar con código legado. También olvídate de las aplicaciones tipo ventana (Windows Forms) a menos que sea necesario. Y centrate solo en .NET y no en .NET Framework.

Domina lo básico antes de entrar al desarrollo web.

2. Aprender ASP .NET MVC

  • Comprende el concepto de Modelo-Vista-Controlador. Aprende WepApi, Api Controllers, Routing, ViewModels y MVVM.
  • No aprendas Razor Pages y/o Blazor (solo si no quieres aprender Javascript).
  • Tampoco Net MAUI.

Si entiendes las bases del Modelo-Vista-Controlador estás listo para el siguiente paso.

3. Aprende HTML, CSS y Javascript (y Typescript)

  • Como maquetar una página web, aprender las etiquetas HTML.
  • Cómo darle estilo a una página web con CSS.
  • Cómo crear eventos con Javascript, cómo usar funciones como fetch, etc.
  • Aprende Typescript, un Javascript de tipado.
  • Entender lo básico de Node JS.
  • Aprende React JS (no empieces con Angular, ya que es más complejo).
  • Crea una aplicación SPA.

Javascript es un mundo, así que siempre vas a encontrar algo nuevo por aprender. Typescript es su "sucesor".

4. Concéntrate en éstos conceptos

  • Comprende lo que es la Inyección de dependencias (Dependency Injection).
  • Entiende sobre código limpio. 
  • Aprende sobre patrones de diseño y principio SOLID.
  • Cómo crear pruebas unitarias (xUnit).
  • Cómo usar logging (Serilog) en tus aplicaciones.

Si ya comprendes estos conceptos, estás listo para lo que sigue.

5. Aprender Sql Server

  • No uses MySQL, Mongo, PostreSQL, etc. Antes aprende a usar Microsoft Sql Server. Como crear bases de datos, tablas, consultas, crear nuevos registros, actualizarlos y eliminarlos.
  • Aprende a usar Entity Framework, el cual es un ORM similar a tecnologías como Hibernate.
  • Aprende a usar LINQ (Language INtegrated Query), una librería que permite integrar capacidades de consulta de datos directamente en el lenguaje.

6. No te centres en cosas sin ningún valor

  • No aprendas Web Forms y/o Windows Communication Foundation (WCF).

7. Crear aplicaciones MVC

  • Crea una aplicación web.
  • Aprende a usar Microsoft Azure (Azure app Service).

Ya estarás listo para crear servicios de mensajería con RabbitMQ o Apache Kafka y cosas más avanzadas. Podrías usar Github Copilot, ChatGPT u otra herramienta similar, pero no abuses de ella pues perderías el objetivo: aprender por ti mismo.

8. Docker y Kubernetes

  • Aprende sobre contenedores con Docker. 
  • Aprende a usar Kubernetes para administrar tus contenedores.

Enlaces:

https://roadmap.sh/aspnet-core
https://www.youtube.com/watch?v=sZVqGIW6Jno

sábado, 18 de octubre de 2025

Consumiendo una API pública con Kotlin & OkHttp

En el pasado post vimos cómo consumir un servicio Node desde una aplicación Java gracias a la librería OkHttp. Esta vez usaremos Kotlin como lenguaje base y Gradle para la administración de las dependencias y ejecución del proyecto.

¿Qué haremos?

1. Comenzaremos con la creación del directorio del proyecto:

$ mkdir proyecto-kotlin
$ cd proyecto-kotlin

El directorio del proyecto se verá así:

proyecto-kotlin/
   .gitattributes
   .gitignore
   .gradle
   .kotlin
   app/
   build/
   gradle/
   gradle.properties
   gradlew
   gradlew.bat
   settings.gradle.kts

2. Agregamos la dependencia de ``OkHttp`` en el archivo ``build.gradle.kts``:

plugins {
    alias(libs.plugins.kotlin.jvm)
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0") // Moved to implementation
    testImplementation("org.jetbrains.kotlin:kotlin-test")
    testImplementation(libs.junit.jupiter.engine)
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation(libs.guava)
    testImplementation("org.junit.jupiter:junit-jupiter:5.10.3")
    testImplementation("org.mockito:mockito-core:5.12.0")
    testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

application {
    mainClass = "org.inforhomex.AppKt"
}

tasks.named<Test>("test") {
    useJUnitPlatform()
}

Con esto se podrá descargar la dependencia.

3. Editamos el programa ``app/src/main/kotlin/org/inforhomex/App.kt``.

package org.inforhomex

import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException

private const val URL_API = "https://api.chucknorris.io/jokes/random"

fun run(client: OkHttpClient = OkHttpClient()) {
    val request = Request.Builder().url(URL_API).build()
    client.newCall(request).execute().use { response ->
        if (!response.isSuccessful) throw IOException("Unexpected code $response")
        for ((name: String, value: String) in response.headers) {
            println("$name: $value")
        }
        println(response.body?.string() ?: "No response body")
    }
}

fun main() {
    run()
}

4. Creamos una prueba unitaria ``AppTest.kt``

package org.inforhomex


import okhttp3.*
import okio.Buffer
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.junit.jupiter.MockitoExtension
import java.io.IOException
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

@ExtendWith(MockitoExtension::class)
class AppTest {

    @Mock
    private lateinit var client: OkHttpClient

    @Mock
    private lateinit var response: Response

    @Mock
    private lateinit var responseBody: ResponseBody

    @Mock
    private lateinit var call: Call

    private val urlApi = "https://api.chucknorris.io/jokes/random"

    @BeforeEach
    fun setUp() {
        
        Mockito.`when`(client.newCall(Mockito.any(Request::class.java))).thenReturn(call)
    }

    @Test
    fun `test run success response`() {
        
        val mockJson = """
            {
                "icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
                "id": "abc123",
                "url": "",
                "value": "Chuck Norris can divide by zero."
            }
        """
        Mockito.`when`(call.execute()).thenReturn(response)
        Mockito.`when`(response.isSuccessful).thenReturn(true)
        Mockito.`when`(response.body).thenReturn(responseBody)
        Mockito.`when`(responseBody.string()).thenReturn(mockJson)
        Mockito.`when`(response.headers).thenReturn(Headers.Builder().add("Content-Type", "application/json").build())

        
        val output = captureOutput {
            run(client) 
        }

        
        assert(output.contains("Content-Type: application/json"))
        assert(output.contains("Chuck Norris can divide by zero."))
    }

    @Test
    fun `test run unsuccessful response throws IOException`() {
       
        Mockito.`when`(call.execute()).thenReturn(response)
        Mockito.`when`(response.isSuccessful).thenReturn(false)
        Mockito.`when`(response.code).thenReturn(404)

       
        val exception = assertFailsWith<IOException> {
            run(client) 
        }
        assertEquals("Unexpected code 404", exception.message)
    }

    
    private fun captureOutput(block: () -> Unit): String {
        val outputStream = java.io.ByteArrayOutputStream()
        val printStream = java.io.PrintStream(outputStream)
        val originalOut = System.out
        System.setOut(printStream)
        try {
            block()
        } finally {
            System.setOut(originalOut)
        }
        return outputStream.toString()
    }
}

5. Compilamos y ejecutamos la aplicación:

$ gradle build
$ gradle run

Si todo va bien, veremos esto en la consola:

date: Sun, 19 Oct 2025 03:25:17 GMT
content-type: application/json
nel: {"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}
report-to: {"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=e%2BRTonTfjrgED0WXfh1o2mxbl6%2BLhQQ4LIu%2F1NhF4MM%3D\u0026sid=812dcc77-0bd0-43b1-a5f1-b25750382959\u0026ts=1760844317"}],"max_age":3600}
reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=e%2BRTonTfjrgED0WXfh1o2mxbl6%2BLhQQ4LIu%2F1NhF4MM%3D&sid=812dcc77-0bd0-43b1-a5f1-b25750382959&ts=1760844317"
server: cloudflare
vary: Origin
vary: Access-Control-Request-Method
vary: Access-Control-Request-Headers
via: 1.1 heroku-router
cf-cache-status: DYNAMIC
cf-ray: 990d2ad69c2f69de-DFW
alt-svc: h3=":443"; ma=86400
{"categories":[],"created_at":"2020-01-05 13:42:20.262289","icon_url":"https://api.chucknorris.io/img/avatar/chuck-norris.png","id":"zDUih4UaS82sDRjSX0hlLQ","updated_at":"2020-01-05 13:42:20.262289","url":"https://api.chucknorris.io/jokes/zDUih4UaS82sDRjSX0hlLQ","value":"Chuck Norris always wanted to surf but couldn't. Everytime his board touches the water, the sea parts."}

¡La aplicación ha funcionado correctamente!

Continuaremos con esta serie de ejemplos en próximas entregas.

Enlaces:

https://square.github.io/okhttp/
https://www.baeldung.com/guide-to-okhttp
https://ironpdf.com/es/java/blog/java-help/okhttp-java/


¿Qué lenguaje de programación debes aprender en un mundo con IA?

Las herramientas de IA están matando, literalmente, a la programación. Cualquiera con un Github Copilot, DeepSeek, Chat GPT, etc. pu...

Etiquetas

Archivo del blog