Un semplice servizio di accorciamento URL con gestione utenti, tracciamento dei link e aggiornamenti in tempo reale tramite WebSocket.
Registra un nuovo utente.
Corpo della richiesta:
{
"username": "john_doe",
"email": "[email protected]",
"password": "password123"
}Risposta:
{
"message": "Utente registrato con successo"
}Effettua il login e ottieni un token JWT.
Corpo della richiesta:
{
"username": "john_doe",
"password": "password123"
}Risposta:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"type": "Bearer",
"username": "john_doe"
}Cambia la password dell'utente già autenticato.
Header:
Authorization: Bearer <jwt_token>
Corpo della richiesta:
{
"oldPassword": "nonsecure",
"newPassword": "password123"
}Risposta:
{
"message": "Password cambiata con successo"
}Crea un URL accorciato (richiede autenticazione).
Header:
Authorization: Bearer <jwt_token>
Corpo della richiesta:
{
"originalUrl": "https://example.com/very/long/url",
"shortCode": "custom123",
"expirationDate": "2024-12-31T23:59:59"
}Note:
shortCodeè opzionale (generato casualmente se non fornito)expirationDateè opzionale (non scade mai se non fornita)
Risposta:
{
"id": 1,
"originalUrl": "https://example.com/very/long/url",
"shortCode": "custom123",
"shortUrl": "http://localhost:8080/custom123",
"createdAt": "2024-01-15T10:30:00",
"expirationDate": "2024-12-31T23:59:59",
"visitCount": 0
}Aggiorna un URL accorciato (richiede autenticazione).
Header:
Authorization: Bearer <jwt_token>
Corpo della richiesta:
{
"originalUrl": "https://example.com/very/long/url",
"expirationDate": "2024-12-31T23:59:59"
}Note:
shortCodenon può essere modificato- i due valori vengono rispettivamente aggiornati solo se forniti
Risposta:
{
"id": 1,
"originalUrl": "https://example.com/very/long/url",
"shortCode": "custom123",
"shortUrl": "http://localhost:8080/custom123",
"createdAt": "2024-01-15T10:30:00",
"expirationDate": "2024-12-31T23:59:59",
"visitCount": 0
}Elimina un URL accorciato (richiede autenticazione). Header:
Authorization: Bearer <jwt_token>
Risposta:
{
"message": "URL eliminato con successo"
}Recupera tutti gli URL dell’utente autenticato.
Header:
Authorization: Bearer <jwt_token>
Risposta:
[
{
"id": 1,
"originalUrl": "https://example.com/very/long/url",
"shortCode": "custom123",
"shortUrl": "http://localhost:8080/custom123",
"createdAt": "2024-01-15T10:30:00",
"expirationDate": "2024-12-31T23:59:59",
"visitCount": 5
}
]Ottieni statistiche dettagliate dell'ultima settimana per uno specifico URL (richiede autenticazione e proprietà).
Header:
Authorization: Bearer <jwt_token>
Risposta:
{
"shortCode": "custom123",
"visitCount": 5,
"visits": [
{
"id": 1,
"visitDate": "2024-01-15T14:30:00",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
]
}Ottieni statistiche dettagliate per uno specifico URL e in uno specifico lasso di tempo (richiede autenticazione e proprietà).
Note:
- è stata scelta una richiesta di tipo POST per inserire il range come body JSON
Header:
Authorization: Bearer <jwt_token>
Corpo della richiesta:
{
"startDate": "2023-12-31T23:59:59",
"endDate": "2024-12-31T23:59:59"
}Risposta:
{
"shortCode": "custom123",
"visitCount": 5,
"visits": [
{
"id": 1,
"visitDate": "2024-01-15T14:30:00",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
]
}Ottieni statistiche relativi a tutti gli URL dell'account autenticato in uno specifico lasso di tempo (richiede autenticazione).
Note:
- è stata scelta una richiesta di tipo POST per inserire il range come body JSON
Header:
Authorization: Bearer <jwt_token>
Corpo della richiesta:
{
"startDate": "2023-12-31T23:59:59",
"endDate": "2024-12-31T23:59:59"
}Risposta:
{
"visitCount": 5,
"visitDetailedCounter": {
"abc123": 3,
"xyz789": 2
},
"visits": [
{
"id": 1,
"shortCode": "abc123",
"visitDate": "2024-01-15T14:30:00",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
]
}Reindirizza all'URL originale e traccia la visita.
Risposta:
- HTTP 302 reindirizza all'URL originale
- HTTP 404 se il codice non è trovato o è scaduto
Connettersi a /ws con token JWT come parametro nella query:
ws://localhost:8080/ws?token=<jwt_token>
Iscriversi a /topic/url/{shortCode} per ricevere aggiornamenti live sulle visite:
Formato del messaggio:
{
"shortCode": "custom123",
"visitCount": 6,
"lastVisit": {
"visitDate": "2024-01-15T15:45:00",
"ipAddress": "192.168.1.101",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)"
}
}Il file GlobalExceptionHandler gestisce le eccezioni globali dell'applicazione, fornendo risposte JSON standardizzate per ogni tipo di errore.
Ogni risposta di errore segue il seguente formato JSON:
{
"timestamp": "2024-01-15T10:30:00",
"status": 400,
"error": "Bad Request",
"message": "Descrizione dell'errore",
"path": "/api/urls"
}- timestamp: Data e ora in cui si è verificato l'errore.
- status: Codice di stato HTTP associato all'errore.
- error: Descrizione dello stato HTTP.
- message: Messaggio dettagliato dell'errore.
- path: Percorso dell'endpoint che ha generato l'errore.
Quando un token JWT è invalido, scaduto o malformato, viene restituito un errore con stato 401 Unauthorized.
{
"timestamp": "2024-01-15T10:30:00",
"status": 401,
"error": "Unauthorized",
"message": "Token JWT non valido",
"path": "/api/urls"
}Quando un utente tenta di accedere a una risorsa senza le autorizzazioni necessarie, viene restituito un errore con stato 403 Forbidden.
{
"timestamp": "2024-01-15T10:30:00",
"status": 403,
"error": "Forbidden",
"message": "Accesso negato",
"path": "/api/urls"
}Per tutte le altre eccezioni non gestite specificamente, viene restituito un errore con stato 500 Internal Server Error.
{
"timestamp": "2024-01-15T10:30:00",
"status": 500,
"error": "Internal Server Error",
"message": "Errore interno del server",
"path": "/api/urls"
}- Il formato della risposta è progettato per essere leggibile e facilmente interpretabile dai client.
- Ogni tipo di errore è associato a un codice di stato HTTP appropriato.
- Gli errori di validazione includono dettagli specifici per ogni campo non valido.
- Implementare rate limiting per prevenire abusi del servizio.
- Utilizzare i DTO anche per le risposte degli endpoint per garantire coerenza.
- Effettuare migliori validazioni sui DTO lato backend.
- Implementare ReCaptcha per prevenire spam nei form di registrazione e login.
- Rendere la grafica del frontend più responsive e user-friendly.

