Translate

Mostrando las entradas con la etiqueta Kemal. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Kemal. Mostrar todas las entradas

domingo, 25 de enero de 2026

API REST con Crystal, Kemal y SQLite


En este post vamos a crear una API REST usando el lenguaje Crystal, el microframework Kemal, y la base de datos SQLite, sin depender de ORMs.

El objetivo: lograr una API rápida, compilada a binario, y con sintaxis clara.

Asegurate de tener instalado:

  • Crystal
  • Shards (el gestor de dependencias)
  • SQLite3


Verificá con:

crystal --version

sqlite3 --version


Creamos el proyecto base:


crystal init app kemal_api

cd kemal_api


Editá el archivo shard.yml y agregá las dependencias:


dependencies:

  kemal:

    github: kemalcr/kemal

  sqlite3:

    github: crystal-lang/crystal-sqlite3


Instalá las dependencias:

shards install


Creamos una base de datos SQLite y una tabla simple:


sqlite3 data.db "CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT);"


A hacer las apis: 


require "kemal"

require "sqlite3"

require "json"


DB_URL = "sqlite3://./data.db"


# --- Funciones de acceso a la base de datos ---

def get_users

  users = [] of Hash(String, String)

  DB.open DB_URL do |db|

    db.query("SELECT id, name, email FROM users") do |rs|

      rs.each do

        users << {

          "id" => rs.read(Int32).to_s,

          "name" => rs.read(String),

          "email" => rs.read(String)

        }

      end

    end

  end

  users

end


def get_user(id : Int32)

  DB.open DB_URL do |db|

    db.query_one?("SELECT id, name, email FROM users WHERE id = ?", id, as: {Int32, String, String})

  end

end


def create_user(name : String, email : String)

  DB.open DB_URL do |db|

    db.exec("INSERT INTO users (name, email) VALUES (?, ?)", name, email)

  end

end


# --- Rutas Kemal ---


get "/users" do

  get_users.to_json

end


get "/users/:id" do |env|

  id = env.params.url["id"].to_i

  if user = get_user(id)

    { id: user[0], name: user[1], email: user[2] }.to_json

  else

    env.response.status_code = 404

    { error: "User not found" }.to_json

  end

end


post "/users" do |env|

  data = JSON.parse(env.request.body.not_nil!)

  create_user(data["name"].as_s, data["email"].as_s)

  env.response.status_code = 201

  { message: "User created" }.to_json

end


Kemal.run



Ejecutá:

crystal run src/kemal_api.cr


La API se levanta en http://localhost:3000


Con Get

curl http://localhost:3000/users


Con Post

curl -X POST http://localhost:3000/users \

  -H "Content-Type: application/json" \

  -d '{"name": "Emanuel", "email": "ema@example.com"}'


Buscar un nuevo users es con id:

curl http://localhost:3000/users/1


Con Crystal + Kemal + SQLite podés construir APIs REST livianas, rápidas y auto-contenidas, ideales para proyectos pequeños o microservicios.

El código es legible, la ejecución veloz, y la experiencia de desarrollo tan fluida como en Ruby, pero con el rendimiento de C.


jueves, 22 de enero de 2026

APIs Ligeras con Crystal y Kemal parte 2


Seguimos con Crystal + Kemal. Podemos simular una API para gestionar usuarios en memoria:


require "kemal"

require "json"


struct User

  property id : Int32

  property name : String

end


users = [

  User.new(id: 1, name: "Alice"),

  User.new(id: 2, name: "Bob")

]


get "/users" do

  users.to_json

end


get "/users/:id" do |env|

  id = env.params.url["id"].to_i

  user = users.find { |u| u.id == id }

  if user

    user.to_json

  else

    env.response.status_code = 404

    { error: "User not found" }.to_json

  end

end


Kemal.run


Con solo unas líneas, tenés una API REST rápida y compilada a código nativo.


Kemal permite agregar middlewares personalizados para logging, autenticación o cabeceras:


before_all do |env|

  puts "Request: #{env.request.method} #{env.request.path}"

end


También incluye un middleware logger integrado:


add_handler Kemal::Logger.new


Gracias al modelo de fibers de Crystal, Kemal puede manejar múltiples requests concurrentes sin bloquear el hilo principal.

Esto lo hace ideal para APIs I/O-bound (por ejemplo, servicios que consultan bases de datos o APIs externas).


get "/async" do

  spawn do

    sleep 1

    puts "Tarea asíncrona completada"

  end

  "Procesando..."

end


Kemal es un ejemplo perfecto del espíritu de Crystal:

  • Sintaxis clara y expresiva.
  • Ejecución compilada, rápida y eficiente.
  • Concurrencia simple y no bloqueante.
  • Framework minimalista y productivo.

Si te gusta Sinatra en Ruby o Express en Node.js, vas a sentirte como en casa, pero con el rendimiento de un lenguaje compilado.

miércoles, 21 de enero de 2026

APIs Ligeras con Crystal y Kemal


Crystal es un lenguaje que combina la velocidad de C con la elegancia de Ruby.

Entre sus frameworks web más populares se destaca Kemal, un microframework minimalista y rápido, muy similar a Sinatra (Ruby) o Express (Node.js).

Primero, asegúrate de tener instalado Crystal.

Podés verificarlo con:

crystal --version


Y si no lo tenés instalado podés ejecutar este comando: 

curl -fsSL https://crystal-lang.org/install.sh | sudo bash


Luego, instalá Kemal agregándolo a tu proyecto con shards, el gestor de dependencias de Crystal.


shards init


Editá el archivo shard.yml y agregá:


dependencies:

  kemal:

    github: kemalcr/kemal


Finalmente, instalá las dependencias:


shards install


Creamos un archivo app.cr:


require "kemal"


get "/" do

  "Hola desde Crystal con Kemal!"

end


Kemal.run


Y ejecutamos:

crystal run app.cr


📍 Luego, abrí http://localhost:3000

Vas a ver la respuesta:


Hola desde Crystal con Kemal!


Kemal permite definir rutas con parámetros y manejar JSON fácilmente:


require "kemal"

require "json"


get "/saludo/:nombre" do |env|

  nombre = env.params.url["nombre"]

  { mensaje: "Hola, #{nombre}!" }.to_json

end


Kemal.run


GET http://localhost:3000/saludo/Emanuel


Responde con:

{"mensaje": "Hola, Emanuel!"}