Compare commits
	
		
			9 Commits
		
	
	
		
			e354433cd6
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d84b5c0853 | |||
| 56819fb1ca | |||
| f96a358227 | |||
| 66fdf8bb3b | |||
| d9196512de | |||
| 5129b517d8 | |||
| 85aa6a38ba | |||
| 7c801b4b73 | |||
| 06d95d32ca | 
							
								
								
									
										
											BIN
										
									
								
								Manual Titulares APP.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Manual Titulares APP.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										180
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| ## 📰 Titulares APP  | ||||
| --- | ||||
| **Titulares APP** es una aplicación web de dashboard en tiempo real diseñada para extraer titulares de un sitio de noticias, gestionarlos y exportarlos automáticamente a un archivo CSV en una ubicación de red. | ||||
|  | ||||
| El sistema se compone de un **backend RESTful API desarrollado en ASP.NET Core** que gestiona el scraping, la base de datos y la comunicación en tiempo real, y un **frontend interactivo de tipo SPA (Single Page Application) construido con React, TypeScript y Vite**. | ||||
|  | ||||
| --- | ||||
| ## 🚀 Funcionalidades Principales | ||||
|  | ||||
| El sistema está diseñado para la automatización, la gestión centralizada y la visualización en tiempo real de titulares de noticias. | ||||
|  | ||||
| ### 🤖 Motor de Scraping Automatizado | ||||
| - **Worker en Segundo Plano:** Un proceso `BackgroundService` de .NET se ejecuta de forma continua en el servidor. | ||||
| - **Scraping Periódico:** Extrae los últimos titulares del sitio de noticias (`eldia.com`) a intervalos configurables. | ||||
| - **Sincronización Inteligente:** Compara los titulares extraídos con los existentes en la base de datos para evitar duplicados y mantener la lista actualizada, preservando el orden de los titulares manuales. | ||||
| - **Limpieza de Datos:** Procesa el texto de los titulares para eliminar prefijos no deseados (ej: "VIDEO.-") y decodificar entidades HTML. | ||||
|  | ||||
| ### ⚡ Actualizaciones en Tiempo Real con SignalR | ||||
| - **Notificación Instantánea:** Cualquier cambio en la lista de titulares (por scraping, creación manual, edición, reordenamiento o eliminación) es notificado instantáneamente a todos los clientes conectados. | ||||
| - **Dashboard Sincronizado:** La tabla de titulares en la interfaz de todos los usuarios se actualiza en tiempo real sin necesidad de refrescar la página. | ||||
| - **Gestión de Conexión:** El backend detecta cuándo hay clientes activos y puede pausar el proceso de scraping si no hay nadie conectado para ahorrar recursos. | ||||
|  | ||||
| ### 🖐️ Gestión Manual Completa | ||||
| - **Creación de Titulares:** Permite añadir titulares manualmente, los cuales se insertan al principio de la lista. | ||||
| - **Edición Rápida:** | ||||
|     - Edición del texto del titular directamente en la tabla. | ||||
|     - Edición de la viñeta (bullet point) a través de un modal dedicado. | ||||
| - **Reordenamiento Drag & Drop:** Permite cambiar el orden visual de los titulares simplemente arrastrándolos y soltándolos en la tabla. | ||||
| - **Eliminación Segura:** Borrado de titulares con un modal de confirmación para evitar acciones accidentales. | ||||
|  | ||||
| ### ⚙️ Panel de Configuración Dinámico | ||||
| - **Gestión Centralizada:** Una sección en la UI permite configurar todos los parámetros clave del sistema. | ||||
| - **Parámetros Configurables:** | ||||
|     - **Ruta del archivo CSV:** Ubicación de red donde se guardará el archivo. | ||||
|     - **Intervalo de Scraping:** Frecuencia en minutos para la extracción de nuevos titulares. | ||||
|     - **Cantidad de Titulares:** Número máximo de titulares a mantener en la lista. | ||||
|     - **Viñeta por Defecto:** Símbolo a usar cuando un titular no tiene una viñeta específica. | ||||
| - **Auto-Guardado Inteligente:** Los cambios en la configuración se guardan automáticamente en la base de datos después de una breve pausa (`debounce`), proporcionando una experiencia de usuario fluida. | ||||
|  | ||||
| ### 📄 Exportación a CSV Robusta | ||||
| - **Generación Automática:** Después de cada ciclo de scraping exitoso, el sistema regenera automáticamente el archivo `titulares.csv` en la ruta de red configurada. | ||||
| - **Generación Manual:** Un botón en la UI permite forzar la regeneración del archivo CSV en cualquier momento. | ||||
| - **Codificación Específica:** El archivo CSV se genera con codificación `UTF-16 Big Endian con BOM` para máxima compatibilidad con sistemas específicos que puedan consumir el archivo. | ||||
|  | ||||
| ### 🎨 Interfaz de Usuario Moderna | ||||
| - **Diseño Oscuro y Profesional:** Construido con Material-UI, ofreciendo una experiencia visual agradable y consistente. | ||||
| - **Feedback al Usuario:** Notificaciones instantáneas para operaciones de éxito o error. | ||||
| - **Indicadores de Estado:** Muestra el estado de la conexión con el servidor (Conectado, Reconectando, Desconectado) y el estado del proceso de scraping (ON/OFF). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🛠️ Stack Tecnológico | ||||
|  | ||||
| ### Backend (`backend/`) | ||||
| - **Framework:** ASP.NET Core 9 | ||||
| - **Lenguaje:** C# | ||||
| - **Acceso a Datos:** Dapper (Micro ORM) | ||||
| - **Base de Datos:** Microsoft SQL Server | ||||
| - **Scraping:** HtmlAgilityPack | ||||
| - **Comunicación Real-Time:** SignalR | ||||
| - **Generación CSV:** CsvHelper | ||||
|  | ||||
| ### Frontend (`frontend/`) | ||||
| - **Librería:** React 19 | ||||
| - **Lenguaje:** TypeScript | ||||
| - **Componentes UI:** Material-UI (MUI) | ||||
| - **Drag & Drop:** dnd-kit | ||||
| - **Comunicación Real-Time:** Cliente de SignalR (`@microsoft/signalr`) | ||||
| - **Build Tool:** Vite | ||||
|  | ||||
| ### Entorno de Producción | ||||
| - **Contenerización:** Docker & Docker Compose | ||||
| - **Proxy Inverso y Servidor Web:** Nginx (configurado para servir React y actuar como proxy para la API y SignalR/WebSockets) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 🚀 Puesta en Marcha (Getting Started) | ||||
|  | ||||
| Siga estos pasos para configurar y ejecutar el proyecto. | ||||
|  | ||||
| ### 1. Entorno de Desarrollo Local | ||||
|  | ||||
| #### Prerrequisitos | ||||
| - **.NET SDK 9.0** o superior. | ||||
| - **Node.js** v20.x o superior. | ||||
| - **Microsoft SQL Server** y una herramienta de gestión como SSMS. | ||||
|  | ||||
| #### Configuración | ||||
| 1.  **Clonar el Repositorio:** | ||||
|     ```bash | ||||
|     git clone <URL_DEL_REPOSITORIO_GITEA> | ||||
|     cd TitularesApp # O el nombre de tu carpeta | ||||
|     ``` | ||||
| 2.  **Base de Datos:** | ||||
|     - Cree una base de datos en su instancia de SQL Server (ej: `TitularesDB`). | ||||
|     - Ejecute los scripts necesarios para crear las tablas `Titulares` y `Configuracion` según los modelos en el proyecto (`Titular.cs`, `ConfiguracionApp.cs`). | ||||
| 3.  **Backend (`backend/src/Titulares.Api`):** | ||||
|     - Renombre o copie `appsettings.Development.json` si es necesario. | ||||
|     - **Modifique la `ConnectionString`** en `appsettings.json` para apuntar a su base de datos. | ||||
|     - Ejecute desde el directorio `backend/src/Titulares.Api`: | ||||
|       ```bash | ||||
|       dotnet restore | ||||
|       dotnet run | ||||
|       ``` | ||||
|     - La API estará escuchando en `http://localhost:5174`. | ||||
| 4.  **Frontend (`frontend/`):** | ||||
|     - Verifique que `frontend/.env.development` contiene `VITE_API_BASE_URL=http://localhost:5174`. | ||||
|     - Ejecute desde el directorio `frontend/`: | ||||
|       ```bash | ||||
|       npm install | ||||
|       npm run dev | ||||
|       ``` | ||||
|     - La aplicación estará disponible en `http://localhost:5173`. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ### 2. Entorno de Producción con Docker | ||||
|  | ||||
| Esta es la forma recomendada de desplegar la aplicación. | ||||
|  | ||||
| #### Prerrequisitos | ||||
| - **Docker** y **Docker Compose** instalados en el servidor anfitrión (ej: `192.168.5.128`). | ||||
| - Una **carpeta compartida en la red** accesible desde el servidor Docker, donde se guardará el archivo CSV. | ||||
|  | ||||
| #### Configuración del Servidor Anfitrión (Host de Docker) | ||||
| Para asegurar que el contenedor pueda escribir en la carpeta de red de forma persistente y resiliente a reinicios, se recomienda configurar un montaje bajo demanda con `autofs`. | ||||
|  | ||||
| 1.  **Instalar dependencias:** `sudo apt-get install -y autofs cifs-utils`. | ||||
| 2.  **Configurar el mapa maestro `auto.master`:** Añadir la línea `/mnt /etc/auto.cifs --timeout=60`. | ||||
| 3.  **Crear el mapa `auto.cifs`** con los detalles de la carpeta compartida, apuntando a un archivo de credenciales seguro. | ||||
|     ``` | ||||
|     # /etc/auto.cifs | ||||
|     nombre_montaje -fstype=cifs,credentials=/ruta/segura/credenciales.txt,uid=1000,gid=1000,vers=3.0 ://IP_PC_USUARIO/CARPETA_COMPARTIDA | ||||
|     ``` | ||||
| 4.  **Reiniciar el servicio:** `sudo systemctl restart autofs`. | ||||
|  | ||||
| #### Despliegue | ||||
| 1.  **Clonar el repositorio** en el servidor Docker. | ||||
| 2.  **Configurar la red externa de Docker** si es necesario (para la base de datos). | ||||
|     ```bash | ||||
|     docker network create shared-net | ||||
|     ``` | ||||
| 3.  **Ejecutar Docker Compose** desde la raíz del proyecto. | ||||
|     ```bash | ||||
|     docker-compose up --build -d | ||||
|     ``` | ||||
| 4.  **Acceder a la Aplicación:** La aplicación estará disponible en la IP del servidor Docker y el puerto configurado en `docker-compose.yml`. | ||||
|     - **URL:** `http://192.168.5.128:8905` | ||||
|  | ||||
| --- | ||||
| ## 📂 Estructura del Proyecto | ||||
|  | ||||
| ``` | ||||
| . | ||||
| ├── backend/ | ||||
| │   └── src/ | ||||
| │       └── Titulares.Api/        # Proyecto principal de ASP.NET Core | ||||
| │           ├── Controllers/      # Controladores de la API | ||||
| │           ├── Data/             # Repositorios (Dapper) para acceso a datos | ||||
| │           ├── Hubs/             # Hubs de SignalR | ||||
| │           ├── Models/           # Clases de modelo y DTOs | ||||
| │           ├── Services/         # Lógica de negocio (Scraping, CSV, Estado) | ||||
| │           ├── Workers/          # Servicios en segundo plano | ||||
| │           ├── Dockerfile        # Instrucciones para construir la imagen del backend | ||||
| │           └── ... | ||||
| ├── frontend/ | ||||
| │   ├── src/ | ||||
| │   │   ├── components/           # Componentes de React | ||||
| │   │   ├── contexts/           # Proveedores de Contexto (Notificaciones) | ||||
| │   │   ├── hooks/              # Hooks personalizados (useSignalR, useDebounce) | ||||
| │   │   ├── services/           # Lógica de llamadas a la API (axios) | ||||
| │   │   ├── App.tsx             # Componente principal de la aplicación | ||||
| │   │   └── main.tsx            # Punto de entrada de React | ||||
| │   ├── .env.development        # Variables de entorno para desarrollo | ||||
| │   ├── .env.production         # Variables de entorno para producción | ||||
| │   └── Dockerfile              # Instrucciones para construir la imagen del frontend | ||||
| ├── nginx/ | ||||
| │   └── nginx.conf              # Configuración de Nginx como proxy inverso | ||||
| └── docker-compose.yml          # Orquestación de los contenedores | ||||
| ``` | ||||
							
								
								
									
										26
									
								
								backend/src/Titulares.Api/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								backend/src/Titulares.Api/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # Etapa 1: Compilación | ||||
| FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build | ||||
| WORKDIR /src | ||||
|  | ||||
| # 1. Copia solo el archivo .csproj. | ||||
| # La ruta de origen es "Titulares.Api.csproj" porque está en la raíz del contexto. | ||||
| COPY Titulares.Api.csproj . | ||||
|  | ||||
| # 2. Restaura las dependencias. Docker guardará esta capa en caché. | ||||
| RUN dotnet restore "Titulares.Api.csproj" | ||||
|  | ||||
| # 3. Copia el resto de los archivos del proyecto. | ||||
| COPY . . | ||||
|  | ||||
| # 4. Publica la aplicación. | ||||
| # --no-restore se usa porque ya hemos restaurado las dependencias. | ||||
| RUN dotnet publish "Titulares.Api.csproj" -c Release -o /app/publish --no-restore | ||||
|  | ||||
| # Etapa 2: Imagen Final | ||||
| FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final | ||||
| WORKDIR /app | ||||
| COPY --from=build /app/publish . | ||||
|  | ||||
| EXPOSE 8080 | ||||
| ENV ASPNETCORE_ENVIRONMENT=Production | ||||
| ENTRYPOINT ["dotnet", "Titulares.Api.dll"] | ||||
| @@ -23,12 +23,15 @@ builder.Services.AddScoped<CsvService>(); | ||||
| builder.Services.AddSingleton<ConfiguracionRepositorio>(); | ||||
| builder.Services.AddSingleton<EstadoProcesoService>(); | ||||
|  | ||||
| // Obtener los orígenes permitidos desde la configuración | ||||
| var allowedOrigins = builder.Configuration.GetValue<string>("AllowedOrigins")?.Split(',') ?? new[] { "http://localhost:5173" }; | ||||
|  | ||||
| // Añadimos la política de CORS | ||||
| builder.Services.AddCors(options => | ||||
| { | ||||
|     options.AddPolicy("AllowReactApp", builder => | ||||
|     options.AddPolicy("AllowReactApp", policyBuilder => | ||||
|     { | ||||
|         builder.WithOrigins("http://localhost:5173") | ||||
|         policyBuilder.WithOrigins(allowedOrigins) | ||||
|                .AllowAnyHeader() | ||||
|                .AllowAnyMethod() | ||||
|                .AllowCredentials(); | ||||
|   | ||||
							
								
								
									
										11
									
								
								backend/src/Titulares.Api/appsettings.Production.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								backend/src/Titulares.Api/appsettings.Production.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| { | ||||
|   "ConnectionStrings": { | ||||
|     "DefaultConnection": "Server=db-sqlserver;Database=TitularesDB;User Id=titularesApi;Password=PTP847Titulares;TrustServerCertificate=True;" | ||||
|   }, | ||||
|   "AllowedOrigins": "http://192.168.5.128:8905", | ||||
|   "Logging": { | ||||
|     "LogLevel": { | ||||
|       "Default": "Warning"  | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -6,6 +6,7 @@ | ||||
|     } | ||||
|   }, | ||||
|   "AllowedHosts": "*", | ||||
|   "AllowedOrigins": "http://localhost:5173", | ||||
|   "ConnectionStrings": { | ||||
|     "DefaultConnection": "Server=TECNICA3;Database=TitularesDB;User Id=titularesApi;Password=PTP847Titulares;Trusted_Connection=True;TrustServerCertificate=True;" | ||||
|   } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|   "RutaCsv": "C:\\temp\\titulares.csv", | ||||
|   "RutaCsv": "/data/titulares.csv", | ||||
|   "IntervaloMinutos": 15, | ||||
|   "CantidadTitularesAScrapear": 4, | ||||
|   "ScrapingActivo": false | ||||
|   | ||||
							
								
								
									
										46
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| services: | ||||
|   # Servicio del Backend | ||||
|   backend: | ||||
|     build: | ||||
|       context: ./backend/src/Titulares.Api | ||||
|       dockerfile: Dockerfile | ||||
|     container_name: titulares-api | ||||
|     # No exponemos puertos al exterior, el proxy se encarga de eso. | ||||
|     environment: | ||||
|       # Le decimos a ASP.NET Core que escuche en el puerto 8080 en todas las interfaces de red | ||||
|       - ASPNETCORE_URLS=http://+:8080 | ||||
|     volumes: | ||||
|       # Mapea la carpeta del host (que será gestionada por autofs)  | ||||
|       # a una carpeta '/data' dentro de este contenedor. | ||||
|       # La aplicación .NET ahora solo necesita escribir en '/data/titulares.csv'. | ||||
|       - /mnt/autofs/titulares_csv_remoto:/data | ||||
|     networks: | ||||
|       - app-net | ||||
|       - shared-net # Conectamos a la red externa para la DB | ||||
|     restart: unless-stopped | ||||
|  | ||||
|   # Servicio de Nginx (Proxy Inverso + Servidor Frontend) | ||||
|   nginx-proxy: | ||||
|     build: | ||||
|       context: ./frontend # Construimos desde la carpeta del frontend... | ||||
|       dockerfile: Dockerfile # ...usando su Dockerfile para generar los estáticos | ||||
|     container_name: titulares-proxy | ||||
|     # Montamos nuestra configuración personalizada de Nginx | ||||
|     volumes: | ||||
|       - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf | ||||
|     ports: | ||||
|       # Mapeamos el puerto 8905 del host al puerto 80 del contenedor Nginx | ||||
|       - "8905:80" | ||||
|     networks: | ||||
|       - app-net | ||||
|     depends_on: | ||||
|       - backend # Aseguramos que el backend se inicie antes que el proxy | ||||
|     restart: unless-stopped | ||||
|  | ||||
| networks: | ||||
|   # Red interna para la comunicación entre el proxy y el backend | ||||
|   app-net: | ||||
|     driver: bridge | ||||
|   # Definimos la red compartida como externa, ya que fue creada por otro stack | ||||
|   shared-net: | ||||
|     external: true | ||||
							
								
								
									
										1
									
								
								frontend/.env.development
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								frontend/.env.development
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| VITE_API_BASE_URL=http://localhost:5174 | ||||
							
								
								
									
										1
									
								
								frontend/.env.production
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								frontend/.env.production
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| VITE_API_BASE_URL= | ||||
							
								
								
									
										30
									
								
								frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # Etapa 1: Construcción de la aplicación React | ||||
| # Usamos una imagen de Node.js (versión Alpine por ser ligera) | ||||
| FROM node:20-alpine AS build | ||||
| WORKDIR /app | ||||
|  | ||||
| # Copiamos package.json y package-lock.json para instalar dependencias | ||||
| COPY package*.json ./ | ||||
| RUN npm install | ||||
|  | ||||
| # Copiamos el resto de los archivos del frontend | ||||
| COPY . . | ||||
| # Construimos la aplicación para producción. Los archivos resultantes irán a /app/dist | ||||
| RUN npm run build | ||||
|  | ||||
| # Etapa 2: Servidor Nginx | ||||
| # Usamos la imagen oficial de Nginx (versión Alpine por ser ligera) | ||||
| FROM nginx:stable-alpine | ||||
| WORKDIR /usr/share/nginx/html | ||||
|  | ||||
| # Eliminamos el contenido por defecto de Nginx | ||||
| RUN rm -rf ./* | ||||
|  | ||||
| # Copiamos los archivos estáticos construidos en la etapa anterior | ||||
| COPY --from=build /app/dist . | ||||
|  | ||||
| # Exponemos el puerto 80, que es el puerto por defecto de Nginx | ||||
| EXPOSE 80 | ||||
|  | ||||
| # El comando por defecto de la imagen de Nginx es suficiente para iniciar el servidor | ||||
| # CMD ["nginx", "-g", "daemon off;"] | ||||
| @@ -2,9 +2,9 @@ | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||||
|     <link rel="icon" type="image/svg+xml" href="/elDia.ico" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>frontend</title> | ||||
|     <title>Titulares APP</title> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="root"></div> | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								frontend/public/elDia.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								frontend/public/elDia.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 66 KiB | 
| @@ -3,7 +3,10 @@ | ||||
| import { useEffect, useRef, useState } from 'react'; | ||||
| import * as signalR from '@microsoft/signalr'; | ||||
|  | ||||
| const HUB_URL = 'http://localhost:5174/titularesHub'; | ||||
| // La URL base viene de la variable de entorno | ||||
| const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || ''; | ||||
| // Construimos la URL completa del Hub | ||||
| const HUB_URL = `${API_BASE_URL}/titularesHub`; | ||||
|  | ||||
| // Definimos un tipo para el estado de la conexión para más claridad | ||||
| export type ConnectionStatus = 'Connecting' | 'Connected' | 'Disconnected' | 'Reconnecting'; | ||||
|   | ||||
| @@ -3,10 +3,12 @@ | ||||
| import axios from 'axios'; | ||||
| import type { Configuracion, Titular } from '../types'; | ||||
|  | ||||
| const API_URL = 'http://localhost:5174/api'; | ||||
| // La URL base viene de la variable de entorno | ||||
| const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || ''; | ||||
|  | ||||
| const apiClient = axios.create({ | ||||
|   baseURL: API_URL, | ||||
|   // Construimos la URL completa para las llamadas a la API REST | ||||
|   baseURL: `${API_BASE_URL}/api`, | ||||
|   headers: { 'Content-Type': 'application/json' }, | ||||
| }); | ||||
|  | ||||
|   | ||||
							
								
								
									
										46
									
								
								nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| # Define un "upstream" que apunta a nuestro servicio de backend. | ||||
| # 'backend' será el nombre del servicio en docker-compose, y 8080 es el puerto | ||||
| # que expusimos en su Dockerfile. | ||||
| upstream backend_api { | ||||
|     server backend:8080; | ||||
| } | ||||
|  | ||||
| server { | ||||
|     # Nginx escuchará en el puerto 80 DENTRO del contenedor. | ||||
|     listen 80; | ||||
|     server_name 192.168.5.128; # Opcional, puedes usar localhost o tu dominio | ||||
|  | ||||
|     # Ubicación raíz: sirve los archivos de la aplicación React. | ||||
|     location / { | ||||
|         root /usr/share/nginx/html; | ||||
|         try_files $uri /index.html; # Clave para Single Page Applications (SPA) | ||||
|     } | ||||
|  | ||||
|     # Ubicación para la API REST. | ||||
|     # Todas las peticiones a http://.../api/... serán redirigidas al backend. | ||||
|     location /api { | ||||
|         proxy_pass http://backend_api; | ||||
|         proxy_set_header Host $host; | ||||
|         proxy_set_header X-Real-IP $remote_addr; | ||||
|         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||||
|         proxy_set_header X-Forwarded-Proto $scheme; | ||||
|     } | ||||
|  | ||||
|     # ----------- CONFIGURACIÓN CRÍTICA PARA SIGNALR ----------- | ||||
|     # Ubicación para el Hub de SignalR. | ||||
|     location /titularesHub { | ||||
|         proxy_pass http://backend_api; | ||||
|  | ||||
|         # Requerido para que la conexión WebSocket funcione | ||||
|         proxy_http_version 1.1; | ||||
|         proxy_set_header Upgrade $http_upgrade; | ||||
|         proxy_set_header Connection "Upgrade"; | ||||
|         proxy_set_header Host $host; | ||||
|          | ||||
|         # Aumenta el timeout para conexiones de larga duración | ||||
|         proxy_read_timeout 90s; | ||||
|  | ||||
|         # Evita que el proxy almacene en caché la negociación de WebSockets | ||||
|         proxy_cache_bypass $http_upgrade; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user