Real-Time & WebSocket¶
Viana uses STOMP over SockJS for all real-time communication. The server pushes ride events, location updates, and rating prompts to connected clients.
Connection¶
Endpoint: ws://localhost:8080/ws (SockJS fallback: http://localhost:8080/ws)
Authentication: JWT must be sent in the Authorization header during the STOMP handshake.
```javascript const socket = new SockJS('http://localhost:8080/ws'); const client = Stomp.over(socket);
client.connect(
{ Authorization: Bearer ${accessToken} },
() => { / connected / },
(error) => { / auth failed / }
);
```
Header, not query parameter
Previous versions passed the token as ?token=. This has been removed. The token must be in the Authorization: Bearer header. Query parameters are logged by proxies and appear in server access logs.
Message flow overview¶
sequenceDiagram
participant C as Customer
participant S as Server
participant D as Driver
C->>S: STOMP CONNECT (Bearer token)
D->>S: STOMP CONNECT (Bearer token)
C->>S: POST /api/rides (HTTP)
S->>D: /topic/driver/{id}/requests (RideOfferDTO)
D->>S: POST /api/driver/accept (HTTP)
S->>C: /topic/customer/{id}/ride-status (ASSIGNED)
S->>D: /topic/ride/{rideId}/expired (other drivers)
loop Every location update while IN_PROGRESS
D->>S: POST /redis/driver/location (HTTP)
S->>C: /topic/customer/{id}/driver-location
end
D->>S: POST /api/driver/complete (HTTP)
S->>C: /topic/customer/{id}/ride-status (COMPLETED)
S->>D: /topic/driver/{id}/ride-status (COMPLETED)
S->>C: /topic/customer/{id}/ride-rating-prompt
S->>D: /topic/driver/{id}/ride-rating-prompt
Topics reference¶
Customer topics — subscribe after connecting as a customer¶
| Topic | Trigger | Payload |
|---|---|---|
/topic/customer/{customerId}/ride-status |
Driver accepts, arrives, starts, completes, or ride is cancelled/expired | RideStatusDTO |
/topic/customer/{customerId}/driver-location |
Driver location update while ride is IN_PROGRESS |
{ lat, lon } |
/topic/customer/{customerId}/ride-rating-prompt |
Ride transitions to COMPLETED |
RideStatusDTO |
Driver topics — subscribe after connecting as a driver¶
| Topic | Trigger | Payload |
|---|---|---|
/topic/driver/{driverId}/requests |
New ride offer within matching radius | RideOfferDTO |
/topic/driver/{driverId}/ride-status |
Customer cancels an ACCEPTED ride, or ride completes |
RideStatusDTO |
/topic/driver/{driverId}/ride-rating-prompt |
Ride transitions to COMPLETED |
RideStatusDTO |
Ride topics — subscribe to a specific ride¶
| Topic | Trigger | Payload |
|---|---|---|
/topic/ride/{rideId}/expired |
Another driver accepted the same ride | "Ride already assigned" (String) |
Inbound message destinations (driver sends)¶
Drivers can send ride state updates via WebSocket instead of HTTP. Both paths call the same underlying service methods.
| Destination | Body | Equivalent HTTP |
|---|---|---|
/app/driver/accept |
{ rideId } |
POST /api/driver/accept |
/app/driver/arrived |
{ rideId } |
POST /api/driver/arrived |
/app/driver/start |
{ rideId } |
POST /api/driver/start |
/app/driver/complete |
{ rideId } |
POST /api/driver/complete |
/app/driver/location |
{ lat, lon } |
POST /driver/location |
Payload schemas¶
RideStatusDTO¶
json
{
"rideId": 42,
"status": "ACCEPTED",
"driverId": 7
}
driverId is null when the status update originates from the customer (e.g., cancellation).
RideOfferDTO¶
json
{
"rideId": 42,
"message": "New ride request available",
"customerId": 3,
"pickupLocation": { "lat": 43.651, "lon": -79.347 },
"dropoffLocation": { "lat": 43.678, "lon": -79.409 },
"serviceType": "STANDARD",
"estimatedFare": 14.80,
"vehicleID": 5
}
Driver location update (customer receives)¶
json
{ "lat": 43.652, "lon": -79.348 }