261 lines
6.4 KiB
Markdown
261 lines
6.4 KiB
Markdown
# 🔧 Guía de Solución de Errores SSE
|
|
|
|
## Error: "❌ Error en SSE" sin detalles
|
|
|
|
### Diagnóstico Rápido
|
|
|
|
1. **Revisar la consola del navegador**
|
|
- Buscar el nuevo log con `readyState: X (STATE_NAME)`
|
|
- Estados posibles:
|
|
- `0 (CONNECTING)`: El navegador está intentando conectar
|
|
- `1 (OPEN)`: Conexión establecida correctamente
|
|
- `2 (CLOSED)`: Conexión cerrada (error)
|
|
|
|
2. **Verificar la pestaña Network**
|
|
- Buscar la petición a `sse_events.php`
|
|
- Ver el status code:
|
|
- `200`: OK (pero puede haber error en el stream)
|
|
- `401`: No autenticado
|
|
- `500`: Error del servidor
|
|
- `502/504`: Error de proxy/timeout
|
|
|
|
### Solución por Estado
|
|
|
|
#### Estado CLOSED (readyState: 2)
|
|
|
|
**Causa común**: El servidor cierra la conexión inmediatamente
|
|
|
|
**Solución**:
|
|
```bash
|
|
# 1. Verificar logs del servidor
|
|
tail -f /var/log/apache2/error.log
|
|
# o
|
|
tail -f /var/log/nginx/error.log
|
|
|
|
# 2. Probar el endpoint directamente
|
|
curl -N http://localhost:8000/api/sse_events.php?token=demo_token
|
|
|
|
# 3. Ejecutar el diagnóstico completo
|
|
php test_sse_complete.php
|
|
```
|
|
|
|
**Posibles problemas**:
|
|
- PHP cierra la conexión por timeout → Verificar `set_time_limit(0)` en sse_events.php
|
|
- Buffer de salida activo → Verificar que no hay `ob_start()` antes
|
|
- Nginx/Apache cortando la conexión → Configurar proxy buffering off
|
|
|
|
#### Estado CONNECTING (readyState: 0)
|
|
|
|
**Causa común**: El navegador no puede conectar al servidor
|
|
|
|
**Solución**:
|
|
```bash
|
|
# 1. Verificar que el servidor está corriendo
|
|
lsof -i :8000
|
|
|
|
# 2. Verificar firewall
|
|
# macOS
|
|
sudo pfctl -s rules
|
|
|
|
# 3. Probar desde curl
|
|
curl -I http://localhost:8000/api/sse_events.php?token=demo_token
|
|
```
|
|
|
|
### Configuración del Servidor
|
|
|
|
#### Apache (.htaccess)
|
|
```apache
|
|
# Deshabilitar compresión para SSE
|
|
<IfModule mod_headers.c>
|
|
<FilesMatch "sse_events\.php$">
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
|
Header set X-Accel-Buffering "no"
|
|
SetEnv no-gzip 1
|
|
</FilesMatch>
|
|
</IfModule>
|
|
```
|
|
|
|
#### Nginx (nginx.conf)
|
|
```nginx
|
|
location /api/sse_events.php {
|
|
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
|
|
include fastcgi_params;
|
|
|
|
# Deshabilitar buffering para SSE
|
|
fastcgi_buffering off;
|
|
proxy_buffering off;
|
|
|
|
# Timeouts largos
|
|
fastcgi_read_timeout 300s;
|
|
fastcgi_send_timeout 300s;
|
|
}
|
|
```
|
|
|
|
#### PHP-FPM (www.conf)
|
|
```ini
|
|
; Aumentar timeout de ejecución
|
|
request_terminate_timeout = 300s
|
|
|
|
; Permitir más procesos para SSE
|
|
pm.max_children = 50
|
|
pm.start_servers = 10
|
|
pm.min_spare_servers = 5
|
|
pm.max_spare_servers = 20
|
|
```
|
|
|
|
### Pruebas Manuales
|
|
|
|
#### Test 1: Verificar headers
|
|
```bash
|
|
curl -I http://localhost:8000/api/sse_events.php?token=demo_token
|
|
```
|
|
|
|
**Esperado**:
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Content-Type: text/event-stream
|
|
Cache-Control: no-cache, no-store, must-revalidate
|
|
Connection: keep-alive
|
|
X-Accel-Buffering: no
|
|
```
|
|
|
|
#### Test 2: Recibir eventos
|
|
```bash
|
|
curl -N http://localhost:8000/api/sse_events.php?token=demo_token
|
|
```
|
|
|
|
**Esperado**:
|
|
```
|
|
event: connected
|
|
data: {"timestamp":1706300000,"user_id":"token_12345678","mode":"authenticated"}
|
|
|
|
: heartbeat
|
|
```
|
|
|
|
#### Test 3: Diagnóstico completo
|
|
```bash
|
|
php test_sse_complete.php
|
|
```
|
|
|
|
**Esperado**:
|
|
```
|
|
✅ Headers SSE correctos
|
|
[1] 📨 Evento: connected
|
|
📦 Data: {
|
|
"timestamp": 1706300000,
|
|
"user_id": "token_12345678",
|
|
"mode": "authenticated"
|
|
}
|
|
```
|
|
|
|
### Solución de Problemas Comunes
|
|
|
|
#### Error: "net::ERR_INCOMPLETE_CHUNKED_ENCODING"
|
|
|
|
**Causa**: El servidor termina el stream abruptamente
|
|
|
|
**Solución**:
|
|
1. Verificar que no hay errores PHP en el stream
|
|
2. Aumentar `max_execution_time` en php.ini
|
|
3. Verificar que no hay `exit()` o `die()` en el loop SSE
|
|
|
|
#### Error: "Failed to fetch"
|
|
|
|
**Causa**: CORS o credenciales
|
|
|
|
**Solución**:
|
|
```javascript
|
|
// En conversations.php, verificar que se usa:
|
|
this.eventSource = new EventSource(sseUrl, {
|
|
withCredentials: true
|
|
});
|
|
```
|
|
|
|
```php
|
|
// En sse_events.php, agregar headers CORS:
|
|
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
|
|
header('Access-Control-Allow-Credentials: true');
|
|
```
|
|
|
|
#### Error: Connection timeout después de 30s
|
|
|
|
**Causa**: Servidor proxy cortando conexión
|
|
|
|
**Solución Apache**:
|
|
```apache
|
|
Timeout 300
|
|
KeepAliveTimeout 300
|
|
```
|
|
|
|
**Solución Nginx**:
|
|
```nginx
|
|
proxy_read_timeout 300s;
|
|
proxy_connect_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
```
|
|
|
|
### Debugging Avanzado
|
|
|
|
#### Habilitar logs detallados PHP
|
|
```php
|
|
// Agregar al inicio de sse_events.php
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 0); // No mostrar en stream
|
|
ini_set('log_errors', 1);
|
|
ini_set('error_log', '/tmp/sse_debug.log');
|
|
```
|
|
|
|
#### Monitorear eventos en tiempo real
|
|
```bash
|
|
# Terminal 1: Ver logs
|
|
tail -f /tmp/sse_debug.log
|
|
|
|
# Terminal 2: Conectar SSE
|
|
php test_sse_complete.php
|
|
|
|
# Terminal 3: Enviar evento de prueba
|
|
curl -X POST http://localhost:8000/api/push_event.php \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"event":"test","data":{"message":"Prueba"},"target":"all"}'
|
|
```
|
|
|
|
### Checklist de Verificación
|
|
|
|
- [ ] El servidor está corriendo en el puerto esperado
|
|
- [ ] Los headers SSE están correctos (Content-Type: text/event-stream)
|
|
- [ ] No hay buffering de salida activo
|
|
- [ ] El endpoint responde con HTTP 200
|
|
- [ ] Se recibe el evento 'connected' al conectar
|
|
- [ ] Los eventos tienen el formato correcto (event: XXX\ndata: {}\n\n)
|
|
- [ ] El archivo de eventos temporal es escribible (/uploads/)
|
|
- [ ] Los logs no muestran errores PHP
|
|
- [ ] El navegador no está bloqueando la conexión (CORS)
|
|
- [ ] La autenticación está funcionando (sesión o token)
|
|
|
|
### Contacto y Soporte
|
|
|
|
Si después de seguir esta guía el problema persiste:
|
|
|
|
1. Ejecutar `php test_sse_complete.php` y copiar la salida completa
|
|
2. Verificar `/tmp/sse_debug.log` y copiar los últimos 50 líneas
|
|
3. Revisar la consola del navegador y copiar todos los logs relacionados con SSE
|
|
4. Verificar Network tab y copiar headers/response de sse_events.php
|
|
|
|
## Mejoras Implementadas
|
|
|
|
### 1. Mejor Logging en Cliente (conversations.php)
|
|
- ✅ Log detallado del readyState con nombre del estado
|
|
- ✅ Limpieza de timeout antes de reconectar
|
|
- ✅ Try-catch al cerrar EventSource
|
|
|
|
### 2. Mejor Manejo en Servidor (sse_events.php)
|
|
- ✅ Límite de tiempo de conexión (5 minutos)
|
|
- ✅ Detección de cliente desconectado
|
|
- ✅ Logs más detallados con trace completo
|
|
- ✅ Headers optimizados para diferentes servidores
|
|
|
|
### 3. Herramientas de Diagnóstico
|
|
- ✅ test_sse_complete.php: Prueba completa de conexión
|
|
- ✅ Parseo de eventos en tiempo real
|
|
- ✅ Medición de tiempos de conexión
|