El día de hoy te mostraré cómo crear un servidor HTTP (servidor web) en Android usando Flutter y Dart. Al final vas a poder levantar un web server desde una APK programada con Android y, obviamente, escuchar peticiones a través de toda la red o desde el propio dispositivo.
Vamos a usar la clase HttpServer.
Crear servidor HTTP con Flutter en Android
El código es realmente sencillo:
var ip = InternetAddress.anyIPv4;
const int puertoServidor = 8000;
var servidor = await HttpServer.bind(ip, puertoServidor);
En este caso estamos iniciando el servidor en localhost:8000. Siempre puedes cambiar el puerto, aunque en mi experiencia nunca he podido usar el puerto 80 porque me parece que los puertos del 1024 hacia abajo están reservados.
De cualquier manera, existen varios puertos que puedes usar.
Manejando peticiones
Una vez que has creado el servidor web en Android con Flutter puedes responder a las peticiones en un ciclo. Toma en cuenta que la variable petición (HttpRequest) es la petición del cliente, y para responderle usamos la propiedad response
que es un HttpResponse.
await for (var peticion in servidor) {
// Aquí manejar la petición
}
Puedes añadir encabezados a la respuesta:
peticion.response
..headers.add("Access-Control-Allow-Origin", "*")
..headers.add("Access-Control-Allow-Headers", "*")
..headers
.add("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT,OPTIONS");
Acceder al método usado en method
(GET, POST, PUT, OPTIONS etcétera):
if (peticion.method == "OPTIONS") {
// Manejar if
}
Y obviamente responder la petición usando write
. En el siguiente ejemplo codificamos el valor true como JSON usando jsonEncode:
peticion.response
..headers.contentType = ContentType("text", "json", charset: "utf-8")
..statusCode = 200
..write(jsonEncode(true))
..close();
También podrías simplemente usar peticion.response.write("Hola mundo")
e invocar a peticion.response.close()
cuando lo consideres necesario.
Ejemplo con aplicación Android y Flutter
Ya te mostré cómo crear el servidor web usando Flutter y HttpServer. En mi caso he encerrado todo el comportamiento en una función a la que le paso 2 funciones callback como parámetros, una en caso de éxito y otra en caso de error.
iniciarServidor(Function(String) onExito, Function(String) onFracaso) async {
try {
var ip = InternetAddress.anyIPv4;
var servidor = await HttpServer.bind(ip, puertoServidor);
onExito(ip.address);
await for (var peticion in servidor) {
peticion.response
..headers.contentType = ContentType("text", "json", charset: "utf-8")
..statusCode = 200
..write(jsonEncode(true))
..close();
}
} catch (e) {
onFracaso(e.toString());
}
}
Tengo la función iniciarServidor
en un archivo llamado servidor.dart
. Después, para usarla en mi main.dart
hago lo siguiente en el initState
:
class _MyHomePageState extends State<MyHomePage> {
var servidorEncendido = false;
var mensajeDeError = "";
var ipDelServidor = "";
@override
void initState() {
super.initState();
iniciarServidor((ip) {
setState(() {
servidorEncendido = true;
mensajeDeError = "";
ipDelServidor = ip;
});
}, (error) {
setState(() {
servidorEncendido = false;
mensajeDeError = error;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
);
}
}
Cuando mi app de Android es iniciada el servidor también se inicia, y gracias a las variables podemos mostrar si el servidor se ha iniciado correctamente.
Estos servidores web con Flutter en Android sirven para varias cosas, entre ellas el permitir que los navegadores web se comuniquen con el dispositivo usando JavaScript del lado del cliente haciendo peticiones HTTP a localhost.
Puedes ver un ejemplo real con mi plugin para impresoras térmicas que convierte peticiones HTTP a comandos ESC POS para enviarlos por Bluetooth o en mi proxy con Android.