Swift del lado del ServidorVapor

Vapor – Instalación y Primeros Pasos

En este tutorial hablaremos sobre Vapor, un framework web para desarrollo backend en Swift. Orientado a protocolos, con un diseño expresivo, enfocado en la seguridad y en la mantenibilidad del código.

Gracias a Vapor los programadores Swift ya no necesitaremos de alternativas en otros lenguajes para dar soporte a nuestras aplicaciones. Mediante Vapor podemos crear tanto una API REST como un backend para toda una web. Vapor lleva a Swift del lado del servidor, dando acceso a un mundo de más posibilidades.

Vapor nace justo luego de que Swift fuera liberado como proyecto Open Source por Apple. Actualmente es de los frameworks más importantes y de mayor crecimiento, compitiendo fuertemente con soluciones similares como Kitura de IBM y Perfect.

Instalación en macOS

En este artículo asumimos que el lector no sólo conoce lo que es un lenguaje de programación, sino que también ya tiene algo de experiencia programando y claramente domina el lenguaje Swift. Además, que está familiarizado con el protocolo HTTP, se desenvuelve con la terminal y tiene ya instalado el comando brew.

De no ser así, le recomendamos leer sobre estos temas, aprenderlos y por último ir a nuestro artículo sobre cómo configurar nuestro entorno de desarrollo Swift en macOS.

Sin más preámbulo abrimos la terminal y antes que nada verificamos que nuestro sistema es compatible, ejecutando lo siguiente:

Verificamos que nuestro sistema es compatible con Vapor y sus dependencias.

Una vez analizada la compatibilidad, pasamos a instalar Vapor con el siguiente comando:

Instalamos Vapor mediante: brew install vapor

Comprobamos que la instalación ha finalizado correctamente haciendo una llamada al comando vapor y mostrando su versión:

Verificamos que todo ha quedado bien mostrando la versión de Vapor con: vapor version

Instalación en Linux

En el caso de Linux asumimos que el lector ya tiene instalado Swift, de no ser así, le recomendamos nuestra guía sobre cómo instalar Swift en Linux, específicamente en Ubuntu.

Con este último punto ya solucionado pasamos al siguiente, donde vamos a instalar Vapor y en el cual también pudiéramos instalar Swift.

Pero ¿por qué no recomiendo instalar Swift de esta manera si es mucho más sencilla? pues básicamente porque no es el repositorio oficial del proyecto Swift, aunque sí lo es de Vapor.

Lo que sucede es que estos últimos pueden responder por su producto, pero no por Swift. Así con tal de evitar un mal empaquetamiento o un problema de seguridad, prefiero instalar Swift a mano tal y como se recomienda en el sitio oficial, tema que hemos abordado ampliamente en nuestro artículo en español, enlazado al inicio de esta sección.

Aclarados estos puntos proseguimos instalando las pre-dependencias de Vapor:

sudo apt install software-properties-common python-software-properties

Importamos la llave de verificación:

wget -q https://repo.vapor.codes/apt/keyring.gpg -O- | sudo apt-key add –

Agregamos el repositorio oficial de Vapor a nuestro sistema:

sudo eval “$(curl -sL https://apt.vapor.sh)”

Verificamos que el repositorio quedó correctamente instalado en nuestro Ubuntu Server y que las versiones son las correctas con el comando:

sudo apt list -a vapor

La salida en pantalla del comando anterior es:

Listing… Done
vapor/xenial 3.1.6 all
vapor/xenial 3.1.2-4.0.3 all
vapor/xenial 3.1.2-4.0.2 all
vapor/xenial 3.1.2 all

Esto último lógicamente variará en el tiempo por tanto:

Reader analysis is advised!

Continuamos con la instalación:

sudo apt install vapor

Cuando la instalación finaliza, entre las tantas líneas, veremos dos como estas:

Setting up swift (4.1.0) …
Setting up vapor (3.1.6) …

Lo que sucede es que Vapor tiene como dependencia a Swift e instala la versión disponible en los repositorios de Vapor.

En mi caso esto no es un problema ya que en mi $PATH tengo la carpeta de instalación de Swift declarada al inicio y la de /usr/bin del sistema al final. Esto da prioridad al binario de nuestra instalación sobre aquel que acaba de instalar Vapor y que se encuentra en /usr/bin.

Comprobamos que la instalación ha terminado correctamente ejecutando:

vapor –version

La versión en pantalla tiene que coincidir con la versión que estamos instalando.

Punto positivo sobre instalar Swift a través de Vapor

Luego de explicar mis razones sobre por qué abogo por instalar Swift de la manera oficial y siempre mediante el paquete .tar.gz., debo decir que el empaquetado de Swift que hacen los chicos de Vapor no tiene porque fallar, y menos aún tener algún problema de seguridad.

De hecho algo positivo que veo al usar este paquete, es que se supone que ellos han probado Vapor con esta versión y si los brindan en conjunto pues no debe haber ningún problema en cuanto a la interoperabilidad de estos.

No obstante yo uso Vapor con la versión que nos provee el proyecto Swift y jamás Vapor se ha quejado de nada. Usarlo de una manera o de otra ya queda a elección del lector.

Creando un Proyecto

Ahora, nos movemos a nuestra carpeta de proyecto (o a donde queramos) y aquí vamos a crear nuestra primera aplicación, a la cual llamaremos (de manera muy original) HelloWorld:

Creamos nuestro primer proyecto con: vapor new HelloWorld

En el caso de Linux (también puede suceder en macOS) como era un sistema acabado de instalar, Vapor me dio un error asociado a Git, con el mensaje:

*** Please tell me who you are.

Es que aún no lo había configurado. Añadiendo nuestro correo y nombre es suficiente, preferiblemente aquellos que tenemos asociados a Github o Bitbucket.

Si no tienes idea de cómo hacerlo te recomiendo nuestro tutorial sobre la instalación y configuración inicial de Git.

Luego de esto y como soy perfeccionista elimino la carpeta del proyecto que me ha creado (a medias) y vuelvo a ejecutar el comando anterior, ahora sí finalizando correctamente.

En este punto lo más aconsejable sería comprobar que todo va bien, así que compilaremos y ejecutaremos nuestra aplicación aún en este estado inicial.

Antes que nada nos cambiamos hacia la carpeta de nuestra aplicación y ejecutamos ambos comandos:

Compilamos y ejecutamos nuestro proyecto con: vapor build y vapor run

En el caso de Linux, si lo ejecutamos de esta manera perderemos el prompt de la terminal mientras nuestra aplicación esté corriendo. Para evitar este inconveniente desde un inicio (luego ya podremos crear un script de arranque), tenemos dos alternativas, o abrimos otra conexión por SSH o ejecutamos el comando junto al símbolo de ampersand (&) de esta forma:

sudo vapor run&

Luego de unos pocos segundos nos saldrán algunos mensajes en la terminal finalizando con el siguiente:

Server starting on http://localhost:8080

La salida en pantalla nos informa que Vapor se encuentra escuchando peticiones en el puerto 8080, este mensaje se muestra tanto en macOS como en Linux, en el caso de este último, si ejecutamos el comando con el ampersand al final, con sólo apretar Enter la terminal nos devolverá el prompt.

Para verificar accedemos mediante nuestro navegador favorito a la dirección:

http://localhost:8080/hello

Si todo está funcionando bien deberíamos de ver algo así:

Comprobando que Vapor funciona correctamente a través de la ruta por defecto.

Nuevamente en el caso de Linux, como estamos en un servidor y no tenemos entorno gráfico, podemos comenzar por comprobar que en efecto está escuchando en el puerto 8080 mediante el comando:

netstat -tnpl

Buscando en la última columna (PID/Progran name) aquella fila donde se lee Run, éste es Vapor.

Luego comprobamos que está funcionando correctamente con el siguiente comando:

curl -s http://localhost:8080/hello && echo

El cual nos debe mostrar el texto:

Hello, world!

Corroborando así que todo está bien.

Para detener nuestro proceso en ejecución o bien listamos los puertos abiertos como acabamos de hacer tomando como referencia el PID de nuestro proceso, que viene siendo el identificador del mismo, o abogamos por este otro comando que nos devuelve el PID en cuestión:

sudo ps | grep Run | awk ‘{print $1}’

Y con este procedemos a matarlo (finalizarlo):

kill -9 26956

Siendo el -9 la máxima prioridad y el número siguiente el PID.

Swift Package Manager

Vapor hace uso del administrador de paquetes nativo de Swift (SPM para abreviar). Mediante este, Vapor gestiona todo el tema de creación de proyectos a partir de los templates con los que cuenta, y lógicamente también las dependencias del mismo.

Digamos así rápidamente que Swift Package Manager es la alternativa a Cocoapods o a Carthage en iOS, el homólogo de las Ruby gems y NPM dentro del mundo Swift. La mayoría de las veces, Vapor Toolbox interactuará con SPM por nosotros. Sin embargo, creo que es muy importante entender de que va todo, al menos lo básico.

Estructura de Directorios

Si listamos el contenido de la carpeta de nuestro proyecto veremos algo similar a esto:

Listamos el contenido de nuestro proyecto con: ls -lh

Una estructura muy similar a la que generamos cuando trabajamos directamente con SPM:

Si tienes dudas sobre lo anterior o te gustaría conocer más, pues te recomiendo hacer una pausa y leer nuestro artículo sobre la gestión de paquetes y dependencias con Swift Package Manager.

Manifiesto del Paquete

Dentro de esta estructura el archivo Package.swift funge como el manifiesto de nuestra aplicación, es el lugar donde definimos el nombre de nuestro paquete así como las dependencias del mismo.

Dependencias

Las dependencias nos son más que otros paquetes como el nuestro y de los cuales depende nuestra aplicación. Todas nuestras aplicaciones con Vapor (como era de esperar) dependerán del paquete Vapor, y de todos aquellos paquetes que se desprendan de este, ya sea para el tema de autenticación de usuarios o trabajos con bases de datos.

La sección dependencias en nuestro manifiesto puede lucir así:

Como podemos constatar, Package.swift viene por defecto con la dependencia antes mencionada del paquete Vapor, mínimo en su versión 3.0.0 y de SQLite para el trabajo con bases de datos y las clásicas operaciones CRUD (Create, Read, Update y Delete), que en todo proyecto necesitamos ejecutar sobre esos datos que persisten en nuestra aplicación.

En Vapor no estamos obligados a trabajar con SQLite, también podemos usar MySQL, PostgreSQL, entre otras.

Objetivos (Targets)

Cuando agregamos una dependencia a nuestro paquete, debemos indicar qué targets dependen de los módulos que acabamos de añadir. Los objetivos o targets son todos aquellos módulos, ejecutables y test (pruebas) que el paquete contiene.

La sección de targets puede lucir así:

Aquí tenemos una sección de targets en relación a las dependencias que acabamos de ver. Por defecto vienen declarados tres targets, el primero llamado App que está asociado a SQLite y a Vapor, el segundo es Run (luego lo veremos cuando usemos Xcode) que hace referencia al target anterior y por último un testTarget mediante el cual llevaremos a cabo nuestra prueba (si es que son necesarias), y que también está asociado al target App.

La mayoría de las aplicaciones de Vapor tendrán estos tres targets, aunque nosotros luego podemos agregar tantos como queramos con tal de organizar nuestro código.

Durante la declaración de cada target especificamos de qué módulos depende. Bueno, este nombre es al que luego hacemos referencia desde nuestro código:

En conjunto a la palabra clave import, tal y como podemos ver en la primera línea del fichero main.swift.

La Carpeta Source

En la carpeta Source tenemos una llamada Run en la cual encontramos un archivo de nombre main.swift:

Listamos el contenido de la carpeta Run con: ls -lh Sources/Run

Este archivo es el punto de entrada a nuestra aplicación, lo que vendría a ser equivalente al atributo @UIApplicationMain que encontramos en el AppDelegate de todos nuestros proyectos iOS.

El fichero main.swift no hay que tocarlo, todo nuestro trabajo lo realizaremos dentro de la carpeta App también dentro de Source, tal y como veremos dentro de poco.

Trabajando con Xcode

Si fueron observadores seguramente notaron que Vapor no creó los ficheros asociados a Xcode, por ende no contamos con una manera de trabajar nuestra aplicación desde Xcode… ¿cierto?

Esto es en parte afirmativo, ya que Vapor se puede trabajar también desde Linux, por esta razón no contempla a Xcode por defecto, sería absurdo generar estos ficheros en un entorno Linux cuando no los podremos utilizar. No obstante si estamos en un Mac, Vapor nos ayuda con la creación de un proyecto Xcode mediante el comando:

Creando nuestro proyecto de Xcode mediante: vapor xcode

El cual crea los ficheros correspondientes y nos abre Xcode al finalizar. Luciendo este último de esta manera:

Xcode en su primer inicio luego de crear los ficheros de proyecto de nuestra aplicación Vapor.

Creando Rutas

En el panel derecho de Xcode o nuestro editor favorito si estamos en Linux, ubicaremos el fichero routes.swift dentro de la carpeta App antes mencionada y que a su vez se encuentra dentro de la carpeta Source.

Al abrir este archivo encontramos el código que mostró el mensaje “Hello, world!” en el navegador. Este código luce así:

Como ya dominamos Swift podemos rápidamente analizar la lógica del código y agregar una nueva ruta bajo esta:

Quedando así:

Declarando nuestra primera ruta.

Para luego ejecutar mediante Xcode nuestra aplicación, no sin antes escoger el scheme Run, cambiando el actual:

Esquema por defecto de nuestra aplicación.

Por:

Buscamos en la lista el esquema Run.

Un cambio que podemos ejecutar fácilmente al hacer click sobre el schema actual y buscando Run en la lista que se despliega:

Antes de ejecutar nuestra aplicación tenemos que cambiar el esquema activo a Run.

Al finalizar todas estas operaciones ejecutamos nuestra aplicación. Esta acción compila automáticamente nuestro proyecto y por último lo ejecuta. Por lo que vamos al navegador y pasamos la nueva dirección basada en la nueva ruta que acabamos de declarar:

Comprobamos nuestra primera ruta a través de Safari.

Recibiendo Datos

Vapor nos permite interactuar de distintas maneras con datos, y no me refiero a las bases de datos, sino a aquellos que pueden llegarnos a través de los parámetros de una URL o de una petición POST hacia una ruta.

Parámetros

Por ejemplo, imaginemos que necesitamos capturar el último parámetro de cierta ruta, digamos que tenemos la siguiente:

http://localhost:8080/hello

Quisiéramos que luego de esto pudiéramos pasar un nombre, es decir, que este último parámetro fuera dinámico con tal de mostrar el saludo a todo aquel que pase su nombre, sin necesidad de declarar una ruta para cada nombre posible.

Con esto en mente podemos declarar la siguiente ruta:

De la cual obtenemos el comportamiento esperado:

Probando una ruta donde capturamos el último parámetro dentro de la URL como el nombre a saludar.

Peticiones POST

Otra alternativa válida y bastante frecuente sería que nos llegase una petición POST con las mismas intenciones pero en formato JSON.

Para el siguiente ejemplo usaremos Postman, una de las mejores aplicaciones para el trabajo con API y de la que ya hemos hablado.

Lo primero que haremos es crear una estructura que represente el bloque JSON que estamos esperando nos llegue desde la petición POST, y que gracias a la magia de Swift 4 y su inigualable gestión de JSON nuestro código será el más sencillo posible.

Por ahora declaremos nuestra estructura al fondo de nuestro archivo routes.swift:

Nuestra estructura la hemos nombrado NameData y esta se complementa con el protocolo Content, el cual básicamente es un wrapper alrededor de Codable.

Dicho lo último, podemos imaginar y afirmar que mediante este protocolo es que Vapor nos facilita el trabajo con los datos que vienen embebidos en la petición POST, ya sea en formato JSONx-www-form-urlencoded.

Cuando hablamos de x-www-form-urlencoded nos referimos a los datos que llegan a nuestro servidor en pares de nombre (de la variable) y valor, estos pares separados por un ampersand (&). Algo muy similar a este ejemplo:

name=charlie&lastname=root

Un formato que, como ya hemos comentado, también es compatible con Vapor y el protocolo Content.

Antes de usar Postman primero vamos nuevamente al archivo routes.swift y agreguemos una nueva ruta que gestione una petición POST como la que estamos esperando recibir. Agreguemos lo siguiente:

Volvemos a ejecutar nuestra aplicación y luego desde Postman ejecutamos la siguiente petición POST a nuestro servidor:

Probando una petición POST a través de Postman.

En la parte inferior podemos ver la respuesta del servidor saludando al nombre que hemos pasado a través del JSON.

Retornando Datos

Como era de esperar Vapor también nos permite devolver un JSON, algo extremadamente necesario para un servicio API. Una funcionalidad que podemos implementar también desde nuestro gestor de rutas, y como hasta ahora, de una manera más que sencilla.

Nuevamente nos apoyamos en Content pero ahora a favor de codificar nuestra estructura hacia JSON. En esta ocasión crearemos una estructura mediante la cual gestionaremos la versión de nuestra API, por ejemplo:

Continuamos con la ruta:

Acto seguido nos vamos al navegador:

Respuesta en formato JSON de nuestra aplicación Vapor ante una petición de tipo GET.

También podemos lograr lo mismo desde Postman, solo tenemos que crear un nuevo request pero esta vez de tipo GET:

Respuesta en formato JSON de nuestra aplicación Vapor ante una petición de tipo GET a través de Postman.

Mi elección personal es hacerlo todo desde Postman, que como pueden observar nos muestra la respuesta JSON en un formato más legible.

Resolviendo Problemas

A lo largo de este artículo, o en cualquier aplicación futura que estemos creando con Vapor,  no podemos descartar encontrarnos con errores. Si este es el caso hay una serie de pasos a seguir para solucionar algunos de estos problemas.

Aunque el tema de errores y hacer debug es algo bien específico a cada proyecto, aquí sólo nos referiremos a esos errores bobos que muchas veces ocurren y que están más del lado de SPM, Xcode o Vapor que del nuestro.

vapor update

Eventualmente nos encontraremos con algún error asociado a Vapor o alguna de nuestras dependencias, errores que muchas veces se encuentran solucionados en las últimas versiones de estos paquetes. Para contrarrestar esto deberíamos trabajar con dependencias actualizadas siempre dentro del branch compatible con nuestra aplicación.

Para lograr esto ejecutamos el comando:

Actualizando las dependencias de nuestra aplicación con: vapor update

Con esto actualizamos tanto Vapor como las dependencias, siempre respetando las limitantes (en cuanto a versiones) declaradas en el fichero Package.swift.

vapor clean

Si estamos teniendo problemas con SPM, ya sea compilando o ejecutando el proyecto, un primer comando a ejecutar sería:

Limpiando los archivos temporales asociados a nuestra aplicación con: vapor clean

vapor xcode

En caso de necesitar regenerar nuestro proyecto de Xcode asociado a nuestro paquete este sería el comando a ejecutar:

Creando nuestro proyecto de Xcode mediante: vapor xcode

Esta acción que ya habíamos visto también nos puede ayudar a solucionar problemas de archivos faltantes (missing files) o errores de configuración a nivel del proyecto de Xcode. Sería básicamente regenerar los ficheros del proyecto nuevamente, esperando que esto pueda resolver los errores ya comentados.

Limpiar y Recompilar

Si luego de todo esto aún seguimos lidiando con errores pues un enfoque sería en Xcode ejecutar Command-Option-Shift-K con el objetivo de limpiar la carpeta de compilación (DerivedData).

De igual manera sería conveniente (en este punto) eliminar la carpeta .build que genera Vapor, de esta manera:

rm -rf .build

Esto elimina todos los derivados de la compilación y sus dependencias. Por último podemos también eliminar el fichero Package.resolved que se encuentra en la raíz de nuestro proyecto:

Eliminando el fichero Package.resolved mediante: rm Package.resolved.

Con esto nos aseguramos de que la próxima vez que compilemos se carguen todas las dependencias en su versión más actualizada.

Conclusiones

Hasta ahora hemos cubierto lo básico de Vapor, en próximos artículos abordaremos otros aspectos de este framework y así poco a poco iremos adentrándonos en funcionalidades más complejas.

Falta aún mucho por aprender en nuestro camino a dominar Vapor. Suscríbete a nuestra lista de correo mediante el formulario en el panel derecho y síguenos en nuestras redes sociales. Mantente así al tanto de todas nuestras publicaciones futuras.

Espero que todo cuanto se ha dicho aquí, de una forma u otra le haya servido de aprendizaje, de referencia y que haya valido su preciado tiempo.

Este artículo, al igual que el resto, será revisado con cierta frecuencia en pos de mantener un contenido de calidad y actualizado.

Cualquier sugerencia, ya sea errores, información o ejemplos a añadir, será más que bienvenida, necesaria!

Josué V. Herrera

Desarrollador Swift / iOS. También he trabajado con otros lenguajes y frameworks como C++ / Qt, Java, C#, Bash Scripting, entre otros. He fungido como administrador de redes, bases de datos y sistemas Linux (y algunos BSD) desde 2005 hasta la actualidad. Me inicio en el mundo Swift y el desarrollo Apple desde el lanzamiento del lenguaje, actualmente me dedico al desarrollo de aplicaciones iOS, a montar VPS (Virtual Private Server) en varias configuraciones y a escribir artículos técnicos. Soy "Experto en Administración y Seguridad de Redes" por la Universidad Tecnológica Nacional FRVM de Argentina.
RECIBE CONTENIDO SIMILAR EN TU CORREO

RECIBE CONTENIDO SIMILAR EN TU CORREO

Suscríbete a nuestra lista de correo y mantente actualizado con las nuevas publicaciones.

Se ha suscrito correctamente!

Close

Adblock Detected

Please consider supporting us by disabling your ad blocker