Skip to main content

Server Overview

The backend is a lightweight Express.js server that acts as an intermediary between the React frontend and the Laravel backend service, while also executing the route-finding algorithm. Location: src/server/server.js
Port: 8080

Server Structure

const express = require("express")
const ServerMockup = require("./ServerMockup")
const findLogic = require("./FindLogic")
const app = express()
The server has three main responsibilities:
  1. Static File Serving - Serves the React application
  2. API Endpoints - Handles route calculation requests
  3. Data Integration - Fetches bus stop data from Laravel backend

Static File Serving

const baseFolder = path.resolve(__dirname, '../../public')
app.use("/", express.static(baseFolder))
All files in the /public directory are served at the root path, including:
  • index.html - Main HTML page
  • main.js - React application bundle
  • vendors.js - Third-party dependencies
  • CSS and other assets

API Endpoints

GET /allRoutes

Retrieves all available bus routes and stops from the backend. Location: src/server/server.js:17-24
app.get("/allRoutes", (req, resp) => {
    ServerMockup()
        .then(busStopsData => resp.json(busStopsData))
        .catch((err) => {
            console.error(err)
            resp.json({ error: err.message })
        })
})
Response Format:
[
    {
        "id": 1,
        "branch_id": 101,
        "stops": [
            {
                "id": 1,
                "name": "Stop Name",
                "latitude": -34.6037,
                "longitude": -58.3816,
                "branch_id": 101
            }
        ]
    }
]
This endpoint is currently unused by the frontend but available for future features like displaying all routes on the map.

POST /route

Calculates the optimal route between two geographic points. Location: src/server/server.js:27-38
app.post("/route", (req, resp) => {
    const routeData = req.body
    ServerMockup()
        .then(busStopsData => {
            const route = findLogic.findRoute(busStopsData, routeData)
            resp.json(route)
        })
        .catch((err) => {
            console.error(err)
            resp.json({ error: err.message })
        })
})
Request Body:
{
    "from": {
        "lat": -34.5593,
        "lng": -58.4569
    },
    "to": {
        "lat": -34.5805,
        "lng": -58.4513
    }
}
Response: Array of stop objects representing the optimal route
[
    {
        "id": 5,
        "name": "Avenida Principal",
        "latitude": -34.5600,
        "longitude": -58.4570,
        "branch_id": 101
    },
    {
        "id": 12,
        "name": "Calle Secundaria",
        "latitude": -34.5750,
        "longitude": -58.4520,
        "branch_id": 101
    }
]

Request Flow Diagram

1

Client Request

Frontend sends POST request to /route with origin and destination
2

Data Retrieval

Server calls ServerMockup() to fetch bus stops from Laravel backend
3

Route Calculation

Server passes bus stops and route parameters to findLogic.findRoute()
4

Algorithm Execution

FindLogic analyzes all possible routes and returns optimal path
5

Response

Server returns array of stops to client as JSON

ServerMockup Integration

The ServerMockup module abstracts the connection to the Laravel backend. Location: src/server/ServerMockup.js
const fetch = require("node-fetch")

module.exports = function () {
    return fetch("http://localhost:8000/branch")
        .then(r => r.json())
        .catch(error => console.error(error.response.data))
}

Purpose

  • Decouples backend logic from data source
  • Makes it easy to swap in different data sources
  • Provides a mockable interface for testing
The name “ServerMockup” suggests this was originally a mock implementation. In production, this would be replaced with actual service integration.

Laravel Backend Contract

The Laravel backend is expected to expose: Endpoint: GET http://localhost:8000/branch Expected Response:
[
    {
        "id": 1,
        "name": "Branch 1",
        "stops": [
            {
                "id": 1,
                "name": "Stop Name",
                "latitude": -34.6037,
                "longitude": -58.3816,
                "branch_id": 1
            }
        ]
    }
]

Middleware Configuration

app.use(express.json())
The express.json() middleware is essential for:
  • Parsing JSON request bodies
  • Making req.body available in route handlers
  • Required for the POST /route endpoint

Error Handling

Current error handling strategy:
.catch((err) => {
    console.error(err)
    resp.json({ error: err.message })
})
Errors are logged to console and returned to client. In production, consider:
  • Using a proper logging service
  • Sanitizing error messages for security
  • Returning appropriate HTTP status codes
  • Implementing error monitoring

Server Initialization

app.listen(8080, () => {
    console.log("Server UP!")
})
The server listens on port 8080 and logs a confirmation message when ready.

Architecture Patterns

Separation of Concerns

The backend demonstrates clear separation:
ComponentResponsibility
server.jsHTTP handling, routing, middleware
ServerMockup.jsExternal data fetching
FindLogic.jsRoute calculation algorithm

Stateless Design

The server maintains no session state:
  • Each request is independent
  • No user authentication or sessions
  • Easily horizontally scalable

Asynchronous Flow

All operations use Promises:
ServerMockup() → Promise<busStopsData>

findLogic.findRoute() → Array<stops>

resp.json() → Send to client

Performance Considerations

Current Limitations

  1. No Caching: Bus stop data is fetched on every request
  2. Synchronous Algorithm: Route finding blocks the event loop
  3. No Request Validation: Input coordinates aren’t validated

Potential Optimizations

Cache bus stop data with periodic refresh:
let cachedData = null
let lastFetch = 0
const CACHE_TTL = 5 * 60 * 1000 // 5 minutes

async function getBusStops() {
    if (cachedData && Date.now() - lastFetch < CACHE_TTL) {
        return cachedData
    }
    cachedData = await ServerMockup()
    lastFetch = Date.now()
    return cachedData
}
Validate coordinates before processing:
function validateCoordinates(point) {
    return point.lat >= -90 && point.lat <= 90 &&
           point.lng >= -180 && point.lng <= 180
}
Prevent abuse with rate limiting:
const rateLimit = require('express-rate-limit')

const limiter = rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 100
})

app.use('/route', limiter)

Security Considerations

Current security gaps:
  • No CORS configuration
  • No input sanitization
  • No authentication/authorization
  • Error messages expose internal details
For production deployment, implement proper security measures including CORS, input validation, authentication, and sanitized error responses.

Next Steps

Learn more about:

Build docs developers (and LLMs) love