API Reference¶
Relevant source files * src/router.js * src/sockets/socketHandler.js
This document provides a comprehensive reference for all API endpoints and real-time communication events in the registro-sesiones system. The API consists of two primary communication channels: traditional HTTP REST endpoints for request-response operations and WebSocket events for real-time bidirectional messaging.
For detailed documentation of individual HTTP endpoints with request/response schemas, see HTTP Endpoints. For WebSocket event specifications, see WebSocket Events.
Authentication¶
Both HTTP and WebSocket APIs use JWT (JSON Web Token) authentication. Tokens are stored in HTTP-only cookies named token and are validated on each request.
Token Structure:
- Signing Algorithm: HS256 (HMAC with SHA-256)
- Secret:
process.env.JWT_SECRET - Expiration: 1 hour (3600 seconds)
- Storage: HTTP-only cookie with
maxAge: 3600000milliseconds - Cookie Name:
token
Token Payload:
{
user: "username", // usuario field from database
name: "display name", // nombre field from database
rol: "admin|user", // rol field from database
imagen: "filename.jpg" // imagen field from database
}
HTTP Authentication Flow:
sequenceDiagram
participant Client
participant src/router.js
participant verifyToken Middleware
participant verifyAdmin Middleware
participant Route Handler
participant MySQL Database
Client->>src/router.js: POST /auth (credentials)
src/router.js->>MySQL Database: SELECT FROM usuarios
MySQL Database-->>src/router.js: User record
src/router.js->>src/router.js: bcrypt.compare(password)
src/router.js->>src/router.js: jwt.sign(payload)
src/router.js-->>Client: Set-Cookie: token=JWT
note over Client,Route Handler: Subsequent authenticated request
Client->>src/router.js: GET /admin (with cookie)
src/router.js->>verifyToken Middleware: Check token
verifyToken Middleware->>verifyToken Middleware: jwt.verify(token)
verifyToken Middleware->>Route Handler: req.user = payload
Route Handler->>MySQL Database: Query data
MySQL Database-->>Route Handler: Results
Route Handler-->>Client: Response
WebSocket Authentication Flow:
sequenceDiagram
participant Socket.IO Client
participant io.use() Middleware
participant setupSocket Handler
participant Socket Rooms
Socket.IO Client->>io.use() Middleware: Connect (HTTP handshake with cookie)
io.use() Middleware->>io.use() Middleware: Extract token from cookie
io.use() Middleware->>io.use() Middleware: jwt.verify(token, JWT_SECRET)
loop [User is Admin]
io.use() Middleware->>setupSocket Handler: socket.request.user = decoded
setupSocket Handler->>Socket Rooms: socket.join("user:username")
setupSocket Handler->>Socket Rooms: socket.join("admins")
setupSocket Handler-->>Socket.IO Client: Connection established
io.use() Middleware-->>Socket.IO Client: Error("Token inválido")
end
Sources: src/router.js L532-L601
src/sockets/socketHandler.js L6-L32
HTTP API Overview¶
The HTTP API is organized into distinct functional areas. All routes are defined in src/router.js
and use Express.js routing.
Endpoint Categories¶
| Category | Routes | Authentication | Description |
|---|---|---|---|
| Public Pages | GET /, GET /login, GET /registro |
None | Landing page and authentication forms |
| Authentication | POST /auth, POST /register |
None (creates token) | User login and registration |
| Product Management | GET /admin, GET /create, GET /edit/:id, GET /delete/:id, POST /save, POST /update |
verifyToken |
CRUD operations for products |
| Support Chat | GET /soporte |
verifyToken |
Real-time chat interface |
| Message APIs | GET /api/mensajes, GET /api/mensajes/mios, GET /api/usuarios-conversaciones |
verifyToken or verifyAdmin |
Message history retrieval |
| PDF Generation | GET /pdf/descargar, GET /pdfkit/descargar |
verifyToken |
Product list export as PDF |
| Localization | GET /set-lang/:lang |
None | Language switching |
| Session | GET /logout |
None | Token removal |
API Endpoint Structure¶
flowchart TD
Home["GET /<br>src/router.js:59-74"]
Login["GET /login<br>src/router.js:75-77"]
Register["GET /registro<br>src/router.js:78-80"]
SetLang["GET /set-lang/:lang<br>src/router.js:398-407"]
AuthPost["POST /auth<br>src/router.js:532-601<br>limiter middleware"]
RegisterPost["POST /register<br>src/router.js:414-484<br>upload.single + validators"]
Logout["GET /logout<br>src/router.js:215-218"]
Admin["GET /admin<br>src/router.js:119-134"]
Soporte["GET /soporte<br>src/router.js:220-227"]
Create["GET /create<br>src/router.js:153-155"]
Edit["GET /edit/:id<br>src/router.js:186-196"]
Delete["GET /delete/:id<br>src/router.js:198-208"]
PDFAdmin["GET /pdfAdmin<br>src/router.js:136-151"]
PDFPuppeteer["GET /pdf/descargar<br>src/router.js:317-353"]
PDFKit["GET /pdfkit/descargar<br>src/router.js:355-396"]
SavePost["POST /save<br>src/router.js:603<br>calls crud.save"]
UpdatePost["POST /update<br>src/router.js:604<br>calls crud.update"]
MensajesMios["GET /api/mensajes/mios<br>src/router.js:256-280"]
APIMensajes["GET /api/mensajes?con=user<br>src/router.js:229-253"]
APIConversaciones["GET /api/usuarios-conversaciones<br>src/router.js:283-315"]
ProductosDB["productos table"]
MensajesDB["mensajes table"]
UsuariosDB["usuarios table"]
AuthPost --> UsuariosDB
RegisterPost --> UsuariosDB
Admin --> ProductosDB
PDFAdmin --> ProductosDB
PDFPuppeteer --> ProductosDB
PDFKit --> ProductosDB
SavePost --> ProductosDB
UpdatePost --> ProductosDB
Edit --> ProductosDB
Delete --> ProductosDB
MensajesMios --> MensajesDB
APIMensajes --> MensajesDB
APIConversaciones --> MensajesDB
APIConversaciones --> UsuariosDB
subgraph subGraph4 ["Database Operations"]
ProductosDB
MensajesDB
UsuariosDB
end
subgraph subGraph3 ["Admin-Only Routes (verifyAdmin)"]
APIMensajes
APIConversaciones
end
subgraph subGraph2 ["Protected Routes (verifyToken)"]
Admin
Soporte
Create
Edit
Delete
PDFAdmin
PDFPuppeteer
PDFKit
SavePost
UpdatePost
MensajesMios
end
subgraph subGraph1 ["Authentication Routes"]
AuthPost
RegisterPost
Logout
end
subgraph subGraph0 ["Public Routes (No Auth)"]
Home
Login
Register
SetLang
end
Sources: src/router.js L1-L607
Middleware Stack by Route Type¶
flowchart TD
Request["HTTP Request"]
Helmet["helmet"]
RateLimit["express-rate-limit"]
CookieParser["cookie-parser"]
BodyParsers["urlencoded + json"]
Session["express-session"]
I18n["i18n.init"]
AuthLimiter["authLimiter<br>POST /auth"]
Upload["multer.single<br>POST /register"]
Validators["express-validator<br>POST /register"]
VerifyToken["verifyToken<br>Protected routes"]
VerifyAdmin["verifyAdmin<br>Admin routes"]
PublicHandler["Public Route Handler"]
AuthHandler["Authentication Handler"]
ProtectedHandler["Protected Route Handler"]
AdminHandler["Admin Route Handler"]
RouteMatch["Route Type?"]
Request --> Helmet
I18n --> RouteMatch
RouteMatch --> PublicHandler
RouteMatch --> AuthLimiter
RouteMatch --> Upload
RouteMatch --> VerifyToken
RouteMatch --> VerifyToken
AuthLimiter --> AuthHandler
Validators --> AuthHandler
VerifyToken --> ProtectedHandler
VerifyAdmin --> AdminHandler
subgraph subGraph2 ["Route Handlers"]
PublicHandler
AuthHandler
ProtectedHandler
AdminHandler
end
subgraph subGraph1 ["Route-Specific Middleware"]
AuthLimiter
Upload
Validators
VerifyToken
VerifyAdmin
Upload --> Validators
VerifyToken --> VerifyAdmin
end
subgraph subGraph0 ["Global Middleware (index.js)"]
Helmet
RateLimit
CookieParser
BodyParsers
Session
I18n
Helmet --> RateLimit
RateLimit --> CookieParser
CookieParser --> BodyParsers
BodyParsers --> Session
Session --> I18n
end
Sources: src/router.js L16-L21
WebSocket API Overview¶
The WebSocket API provides real-time bidirectional communication for the support chat system. The implementation uses Socket.IO library and is configured in src/sockets/socketHandler.js
WebSocket Event Types¶
| Event Name | Direction | Auth Required | Description |
|---|---|---|---|
connection |
Server → Handler | Yes (JWT via cookie) | Initial socket connection established |
mensaje_privado |
Client → Server | Yes | User sends a private message |
mensaje_recibido |
Server → Client | Yes | Server broadcasts received message to recipients |
disconnect |
Client → Server | Yes | Socket connection closed |
Room-Based Routing Architecture¶
flowchart TD
UserA["User: alice<br>Socket Connection"]
UserB["User: bob<br>Socket Connection"]
AdminX["Admin: admin1<br>Socket Connection"]
AdminY["Admin: admin2<br>Socket Connection"]
PersonalA["user:alice<br>Personal Room"]
PersonalB["user:bob<br>Personal Room"]
PersonalX["user:admin1<br>Personal Room"]
PersonalY["user:admin2<br>Personal Room"]
AdminRoom["admins<br>Collective Room"]
Connection["connection event<br>src/sockets/socketHandler.js:36"]
MensajePrivado["mensaje_privado event<br>src/sockets/socketHandler.js:45"]
Disconnect["disconnect event<br>src/sockets/socketHandler.js:65"]
MensajesTable["mensajes table"]
UserA --> PersonalA
UserB --> PersonalB
AdminX --> PersonalX
AdminX --> AdminRoom
AdminY --> PersonalY
AdminY --> AdminRoom
Connection --> PersonalA
Connection --> AdminRoom
MensajePrivado --> PersonalA
MensajePrivado --> PersonalB
MensajePrivado --> AdminRoom
MensajePrivado --> MensajesTable
UserA --> MensajePrivado
AdminX --> MensajePrivado
subgraph Database ["Database"]
MensajesTable
end
subgraph subGraph2 ["setupSocket Handler"]
Connection
MensajePrivado
Disconnect
end
subgraph subGraph1 ["Socket Rooms (io.to)"]
PersonalA
PersonalB
PersonalX
PersonalY
AdminRoom
end
subgraph subGraph0 ["Client Connections"]
UserA
UserB
AdminX
AdminY
end
Sources: src/sockets/socketHandler.js L4-L69
Event Flow: mensaje_privado¶
When a user sends a message via socket.emit("mensaje_privado", {para, mensaje}), the following sequence occurs:
- Server receives event src/sockets/socketHandler.js L45-L63
- Extracts sender from
socket.request.user.user(JWT payload) - Emits to recipient's room via
io.to(user:${para}).emit("mensaje_recibido", ...) - Emits to admins room if sender is not admin via
io.to("admins").emit(...)src/sockets/socketHandler.js L50-L52 - Persists to database via
INSERT INTO mensajessrc/sockets/socketHandler.js L55-L62
sequenceDiagram
participant User Socket
participant (username: bob)
participant socketHandler.js
participant mensaje_privado
participant Socket.IO Rooms
participant mensajes table
participant Admin Socket
participant (in 'admins' room)
participant Recipient Socket
participant (username: alice)
User Socket->>socketHandler.js: emit("mensaje_privado", {para: "alice", mensaje: "Hello"})
socketHandler.js->>socketHandler.js: Extract de = bob from JWT
socketHandler.js->>Socket.IO Rooms: io.to("user:alice")
Socket.IO Rooms->>Recipient Socket: emit("mensaje_recibido", {de: "bob", mensaje: "Hello"})
socketHandler.js->>Socket.IO Rooms: io.to("admins")
Socket.IO Rooms->>Admin Socket: emit("mensaje_recibido", {de: "bob", mensaje: "Hello"})
socketHandler.js->>mensajes table: INSERT (bob, alice, Hello)
mensajes table-->>socketHandler.js: Success
Sources: src/sockets/socketHandler.js L45-L63
Response Formats¶
HTTP JSON Responses¶
API endpoints under /api/* return JSON data:
Success Response Structure:
[
{
"de_usuario": "username",
"para_usuario": "recipient",
"mensaje": "message text",
"fecha": "2024-01-01 12:00:00"
}
]
Error Response Structure:
{
"error": "Error description message"
}
Sources: src/router.js L251
HTTP View Responses¶
Most GET routes render EJS templates and return HTML:
- Content-Type:
text/html - Variables passed via
res.render(view, data) - Common data includes:
user,login,rol,productos,mensajes
Sources: src/router.js L64-L73
PDF Responses¶
PDF generation endpoints return binary PDF data:
- Content-Type:
application/pdf - Content-Disposition:
attachment; filename="productos.pdf" - Response body: PDF binary buffer
Sources: src/router.js L344-L346
WebSocket Event Payloads¶
Client to Server (mensaje_privado):
{
para: "recipient_username",
mensaje: "message text"
}
Server to Client (mensaje_recibido):
{
de: "sender_username",
mensaje: "message text"
}
Sources: src/sockets/socketHandler.js L45
src/sockets/socketHandler.js L48
Error Handling¶
HTTP Error Responses¶
| Status Code | Condition | Example Endpoint |
|---|---|---|
| 400 | Missing required parameters | GET /api/mensajes without ?con= parameter |
| 401 | Invalid or missing JWT token | Any route with verifyToken middleware |
| 403 | Valid token but insufficient permissions | GET /api/mensajes without admin role |
| 404 | Route not found | Non-existent URL path |
| 500 | Database query error or server error | Any route if database connection fails |
Sources: src/router.js L233
WebSocket Error Handling¶
Connection Rejection:
If JWT validation fails during WebSocket handshake, the connection is rejected with an error:
Error: "No autenticado" // No cookies present
Error: "Token no proporcionado" // Cookie exists but no token
Error: "Token inválido" // Token verification failed
Event-Level Errors:
Message persistence errors are logged but do not interrupt message delivery:
console.error("❌ Error al guardar mensaje:", err);
Sources: src/sockets/socketHandler.js L12
src/sockets/socketHandler.js L21
src/sockets/socketHandler.js L30
src/sockets/socketHandler.js L58
Rate Limiting¶
The /auth endpoint (POST login) implements rate limiting via the authLimiter middleware to prevent brute-force attacks:
- Window: 15 minutes
- Max Requests: 5 attempts per IP
- Implementation:
express-rate-limitlibrary - Applied at: src/router.js L532
Sources: src/router.js L21
CORS and Security Headers¶
Security middleware is configured globally in index.js
:
- helmet: Sets various HTTP security headers
- HttpOnly Cookies: JWT token stored in HTTP-only cookies prevents XSS attacks
- Secure Flag: Can be enabled for HTTPS (currently set to
falseat src/router.js L572 )
Sources: src/router.js L570-L574
API Versioning¶
The current API has no explicit versioning. All endpoints are accessed directly without version prefixes (e.g., /api/mensajes not /v1/api/mensajes).
Testing the API¶
For interactive API documentation and testing, the application includes Swagger UI (if configured). Access it at /api-docs when the server is running.
For detailed endpoint specifications including request parameters, response schemas, and example payloads, see:
- HTTP Endpoints - Complete HTTP API reference
- WebSocket Events - Complete WebSocket event reference