Backend
Que el frontend no se pare mientras el backend no está
Acordad el contrato de la API el primer día, trabajad contra una API falsa (un mock) y, cuando el backend esté listo, cambiad una sola línea. Aquí tenéis un generador que funciona en el navegador, sin cuenta ni límites, y la guía para desplegar en virtech.
Tres maneras de hacer un mock
No se excluyen: muchas veces se empieza por la primera y se pasa a la segunda cuando el equipo de frontend necesita un servidor de verdad.
Fuente de datos falsa
Una implementación Fake de la interfaz que usa la app. Es lo más rápido para empezar la UI y lo que usáis en los tests unitarios.
json-server
Una API completa a partir de un db.json: GET, POST, PUT, PATCH y DELETE, filtros, paginación y relaciones. Los cambios se guardan en el fichero. Sirve para todo el equipo y para el móvil.
Prism + OpenAPI
Un mock que responde según el contrato y valida las peticiones. Ideal para los servicios entre equipos: el fichero OpenAPI es el acuerdo entre los dos.
Generador
Describid los recursos y saldrá todo
Los datos se generan en vuestro navegador y no se envían a ningún sitio. El mismo esquema da siempre los mismos datos, lo que va bien para los tests.
Un recurso por línea, sin sangrar, y sus campos debajo, sangrados: nombre: tipo. Un ref enlaza con otro recurso (stationId: ref stations).
idint 0-20number 0-40booltextnameemailaddresslatlngdatedatetimeenum A|Burlref recurso
Con Node.js instalado, en la carpeta del fichero:
npx json-server@0.17.4 --watch db.json --port 8080 --host 0.0.0.0
Ya tenéis GET /stations, GET /stations/1, POST, PUT, PATCH y DELETE, filtros (?status=IN_SERVICE, ?electric_gte=1), paginación (?_page=1&_limit=10) y relaciones (/stations/1/favorites, /favorites?_expand=station).
El contrato, para compartir con el equipo que consumirá vuestro servicio. Abridlo en editor.swagger.io para verlo y, para tener un mock que valida las peticiones:
npx @stoplight/prism-cli mock -h 0.0.0.0 -p 8080 openapi.yaml
En el paquete de datos del proyecto Android. El ViewModel recibe un StationsDataSource: hoy le pasáis el Fake, mañana el que llama a la API con Retrofit.
En lib/data/ del proyecto Flutter. El BLoC recibe un StationsDataSource desde el locator (get_it o el que uséis).
Del mock al backend real, cambiando una línea
La clave es que la UI no sepa de dónde salen los datos. Depende de una interfaz y, al arrancar, la app decide qué implementación pone.
// build.gradle.kts: buildConfigField("boolean", "USE_MOCK", "true") en el build de debug
val dataModule = module {
single<StationsDataSource> {
if (BuildConfig.USE_MOCK) FakeStationsDataSource()
else HttpStationsDataSource(baseUrl = "http://10.0.2.2:8080/")
}
viewModel { StationsViewModel(get()) }
}
const useMock = bool.fromEnvironment('USE_MOCK', defaultValue: true);
const apiUrl = String.fromEnvironment('API_URL', defaultValue: 'http://10.0.2.2:8080');
void setupLocator() {
locator.registerLazySingleton<StationsDataSource>(
() => useMock ? FakeStationsDataSource() : HttpStationsDataSource(apiUrl),
);
}
// flutter run --dart-define=USE_MOCK=false --dart-define=API_URL=http://nattech.fib.upc.edu:40330
localhost de vuestro ordenador es 10.0.2.2. El simulador de iOS usa localhost. Un móvil de verdad en la misma wifi usa la IP local del ordenador (por eso el --host 0.0.0.0). Fuera de casa, virtech.virtech, la nube privada de la FIB
Un servicio de autoservicio de máquinas virtuales para las asignaturas que lo piden, en virtech.fib.upc.edu. Las cuentas os las dan los profesores.
- Máquinas Ubuntu con el usuario
alumne, que puede usarsudo. Sois responsables de todo lo que pase en ellas. - El número de máquinas y su tamaño los fija la cuota de la asignatura. No hay cortafuegos.
- No hay copias de seguridad y se borran al final del cuatrimestre. El código, en GitHub; la configuración, documentada.
- Si perdéis el acceso a una máquina, no se puede recuperar: se borra y se crea otra. Un motivo más para tener la instalación escrita en un script.
Solo red de la FIB
Accesible desde el campus o desde casa con la VPN de la UPC (UPClink). Pero la VPN es personal y solo admite una conexión: no podéis tener a la vez el ordenador y el móvil, ni dar la app a nadie de fuera.
Plantilla sin VPN
Tiene 10 puertos abiertos a Internet a través de nattech.fib.upc.edu, y SSH desde la UPC o con VPN. Cualquier móvil llega, también los de los stakeholders.
Crear la máquina y poner el servicio
- VMs → +, elegid la plantilla, ponedle un nombre y la contraseña del usuario, y Create. Esperad a que pase de DEPLOYING a RUNNING.
- Abrid la Consola (VNC) e iniciad sesión. El mensaje de bienvenida os dice la IP y los puertos. Podéis volver a verlo con
/etc/update-motd.d/99-info-nat. - A partir de aquí, mejor por SSH (desde la UPC o con VPN): calculad el comando abajo.
- Arrancad el servicio escuchando en
0.0.0.0y en un puerto del 8080 al 8089. Si escucha enlocalhost, desde fuera no se llega. - Probadlo desde fuera con el puerto público:
http://nattech.fib.upc.edu:40330.
La que sale en virtech o en el mensaje de bienvenida.
Cómo se calculan los puertos
Todas las máquinas salen a Internet por la misma dirección, nattech.fib.upc.edu, y cada una tiene su rango de puertos según el último número de la IP (172.16.4.XXX):
- SSH: puerto
22000 + XXX. - Servicios: desde el puerto
40000 + XXX·10, diez puertos seguidos que van al 8080-8089 de la máquina.
Instalar Node y dejar el mock en marcha
# Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# desde vuestro ordenador (campus o VPN): subid el db.json
ssh -p 22033 alumne@nattech.fib.upc.edu mkdir -p api
scp -P 22033 db.json alumne@nattech.fib.upc.edu:~/api/
# en la máquina
cd ~/api && npm install json-server@0.17.4
npx json-server --watch db.json --port 8080 --host 0.0.0.0
Para que siga funcionando cuando cerréis la sesión, convertidlo en un servicio:
# /etc/systemd/system/api.service
[Unit]
Description=API PES
After=network.target
[Service]
User=alumne
WorkingDirectory=/home/alumne/api
ExecStart=/home/alumne/api/node_modules/.bin/json-server --watch db.json --port 8080 --host 0.0.0.0
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now api
Con vuestro backend es igual: cambiad el ExecStart por el comando que lo arranca.
¿Cómo compruebo que la conexión funciona, antes de tener ningún servicio?
En la máquina, nc -l -p 8080. En vuestro ordenador, nc nattech.fib.upc.edu 40330 (con vuestro puerto) y escribid cualquier cosa: tiene que aparecer en la máquina.
¿Por qué no me responde el ping?
Por cómo está montado el NAT, el ping no funciona desde fuera de la red de las máquinas, ni siquiera con VPN. Usad curl o nc.
¿Puedo entrar por SSH desde casa sin VPN?
No. Por seguridad, el SSH desde fuera de la UPC solo funciona con la VPN. Los 10 puertos de servicios sí están abiertos a todo el mundo.
He olvidado la contraseña de la máquina.
No se puede recuperar: borrad la máquina y cread una nueva. La contraseña de virtech (no la de la máquina) se cambia en el menú de usuario → Settings → Change password.
La app móvil y el HTTP sin cifrar
nattech sirve HTTP, no HTTPS. Android (desde la versión 9) e iOS bloquean este tráfico por defecto, y la llamada falla sin muchas pistas. Permitidlo solo para este dominio.
<!-- res/xml/network_security_config.xml (en Flutter: android/app/src/main/res/xml/) -->
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="false">nattech.fib.upc.edu</domain>
<domain includeSubdomains="false">10.0.2.2</domain>
</domain-config>
</network-security-config>
<!-- AndroidManifest.xml -->
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
<!-- ios/Runner/Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>nattech.fib.upc.edu</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
Las contraseñas viajan en claro por HTTP. Para PES basta con la excepción por dominio, pero no pongáis contraseñas reales y explicadlo en la documentación como limitación conocida.