% Routing

\section{Routing}

\begin{frame}{Mi a Routing?}
  \begin{block}{Routing}
    A kérések irányítása a megfelelő végpontokra (endpoint).
  \end{block}
  
  \begin{exampleblock}{Route komponensek}
    \begin{itemize}
      \item \textbf{HTTP metódus} - GET, POST, PUT, DELETE
      \item \textbf{URL path} - /api/users, /api/products/:id
      \item \textbf{Handler függvény} - (req, res) => \{\}
    \end{itemize}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Alapvető routing}
  \begin{exampleblock}{Egyszerű route-ok}
    \tiny
    \begin{verbatim}
app.get('/api/users', (req, res) => {
  res.json({ message: 'Get all users' });
});

app.post('/api/users', (req, res) => {
  res.json({ message: 'Create user' });
});

app.put('/api/users/:id', (req, res) => {
  res.json({ message: `Update user ${req.params.id}` });
});

app.delete('/api/users/:id', (req, res) => {
  res.json({ message: `Delete user ${req.params.id}` });
});
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Route paraméterek}
  \begin{exampleblock}{:id paraméter}
    \tiny
    \begin{verbatim}
app.get('/api/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ message: `User ID: ${userId}` });
});

// Több paraméter
app.get('/api/users/:userId/posts/:postId', (req, res) => {
  const { userId, postId } = req.params;
  res.json({ userId, postId });
});
    \end{verbatim}
  \end{exampleblock}
  
  \begin{alertblock}{req.params}
    URL-ben megadott dinamikus értékek.
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Query paraméterek}
  \begin{exampleblock}{Query string}
    \tiny
    \begin{verbatim}
// GET /api/users?page=1&limit=10&role=admin

app.get('/api/users', (req, res) => {
  const { page, limit, role } = req.query;
  
  res.json({
    page: page || 1,
    limit: limit || 10,
    role: role
  });
});
    \end{verbatim}
  \end{exampleblock}
  
  \begin{alertblock}{req.query}
    URL query string paraméterek (?key=value).
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Query - Szűrés, Rendezés, Lapozás}
  \begin{exampleblock}{GET /api/users?page=1\&limit=10\&sort=name\&role=admin}
    \tiny
    \begin{verbatim}
app.get('/api/users', (req, res) => {
  let { page = 1, limit = 10, sort = 'id', role } = req.query;
  
  page = parseInt(page);
  limit = parseInt(limit);
  
  let filteredUsers = users;
  if (role) {
    filteredUsers = filteredUsers.filter(u => u.role === role);
  }
  
  // Rendezés
  filteredUsers.sort((a, b) => a[sort] > b[sort] ? 1 : -1);
  
  // Lapozás
  const start = (page - 1) * limit;
  const paginatedUsers = filteredUsers.slice(start, start + limit);
  
  res.json({ data: paginatedUsers, total: filteredUsers.length });
});
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Express Router létrehozása}
  \begin{exampleblock}{routes/users.js}
    \tiny
    \begin{verbatim}
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.json({ message: 'Get all users' });
});

router.get('/:id', (req, res) => {
  res.json({ message: `Get user ${req.params.id}` });
});

router.post('/', (req, res) => {
  res.json({ message: 'Create user' });
});

router.put('/:id', (req, res) => {
  res.json({ message: `Update user ${req.params.id}` });
});

module.exports = router;
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Router importálása}
  \begin{exampleblock}{app.js}
    \tiny
    \begin{verbatim}
const express = require('express');
const app = express();

const userRoutes = require('./routes/users');
const productRoutes = require('./routes/products');

app.use(express.json());
app.use('/api/users', userRoutes);
app.use('/api/products', productRoutes);

app.listen(3000);
    \end{verbatim}
  \end{exampleblock}
  
  \begin{alertblock}{Prefix}
    Az \texttt{app.use('/api/users', userRoutes)} minden route-hoz hozzáadja a prefix-et.
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Nested (beágyazott) route-ok}
  \begin{exampleblock}{Hierarchikus erőforrások}
    \tiny
    \begin{verbatim}
// GET /api/users/:userId/posts
router.get('/:userId/posts', (req, res) => {
  const { userId } = req.params;
  res.json({ message: `Posts for user ${userId}` });
});

// GET /api/users/:userId/posts/:postId
router.get('/:userId/posts/:postId', (req, res) => {
  const { userId, postId } = req.params;
  res.json({ message: `User ${userId}, Post ${postId}` });
});

// POST /api/users/:userId/posts
router.post('/:userId/posts', (req, res) => {
  const { userId } = req.params;
  res.json({ message: `Create post for user ${userId}` });
});
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Controller-ek használata (1/2)}
  \begin{block}{Separation of Concerns}
    Route-ok csak az útvonalat definiálják, Controller-ek tartalmazzák a logikát.
  \end{block}
  
  \begin{exampleblock}{controllers/user.controller.js}
    \tiny
    \begin{verbatim}
exports.getAllUsers = async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

exports.getUserById = async (req, res) => {
  try {
    const user = await User.findById(req.params.id);
    if (!user) return res.status(404).json({ error: 'Not found' });
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Controller-ek használata (2/2)}
  \begin{exampleblock}{routes/users.js}
    \tiny
    \begin{verbatim}
const express = require('express');
const router = express.Router();
const userController = require('../controllers/user.controller');

router.get('/', userController.getAllUsers);
router.get('/:id', userController.getUserById);
router.post('/', userController.createUser);
router.put('/:id', userController.updateUser);
router.delete('/:id', userController.deleteUser);

module.exports = router;
    \end{verbatim}
  \end{exampleblock}
  
  \begin{alertblock}{Tiszta kód}
    Route fájlok rövidek, Controller-ekben a logika.
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{Middleware route-okban}
  \begin{exampleblock}{Auth middleware route-ra}
    \tiny
    \begin{verbatim}
const auth = require('../middlewares/auth');

router.get('/protected', auth, (req, res) => {
  res.json({ message: 'Protected data' });
});

router.post('/users', auth, validateUser, userController.createUser);

// Minden route-ra
router.use('/admin', auth, adminRoutes);
    \end{verbatim}
  \end{exampleblock}
  
  \begin{alertblock}{Több middleware}
    Több middleware függvényt is alkalmazhatsz sorban.
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{API verziókezelés (1/2)}
  \begin{exampleblock}{Verziókezelés URL-ben}
    \tiny
    \begin{verbatim}
// V1 routes
const v1Routes = require('./routes/v1');
app.use('/api/v1', v1Routes);

// V2 routes
const v2Routes = require('./routes/v2');
app.use('/api/v2', v2Routes);
    \end{verbatim}
  \end{exampleblock}
  
  \begin{exampleblock}{Struktúra}
    \tiny
    \begin{itemize}
      \item routes/v1/index.js
      \item routes/v1/users.js
      \item routes/v1/products.js
      \item routes/v2/index.js
      \item routes/v2/users.js
    \end{itemize}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=10]{API verziókezelés (2/2)}
  \begin{exampleblock}{routes/v1/index.js}
    \tiny
    \begin{verbatim}
const express = require('express');
const router = express.Router();
const userRoutes = require('./users');
const productRoutes = require('./products');

router.use('/users', userRoutes);
router.use('/products', productRoutes);

module.exports = router;
    \end{verbatim}
  \end{exampleblock}
  
  \begin{exampleblock}{Használat}
    \tiny
    \begin{verbatim}
GET /api/v1/users
GET /api/v2/users
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[shrink=10]{Route Best Practices}
  \begin{alertblock}{Konvenciók}
    \begin{enumerate}
      \item Használj \textbf{főneveket}: \texttt{/users}, \texttt{/products}
      \item Használj \textbf{többes számot}: \texttt{/users} $\checkmark$
      \item \textbf{Hierarchia}: \texttt{/users/:userId/posts/:postId}
      \item \textbf{Kisbetűs URL}: \texttt{/api/users} $\checkmark$
      \item \textbf{Kötőjel}: \texttt{/user-profiles} $\checkmark$
      \item \textbf{Verziókezelés}: \texttt{/api/v1/users}
      \item \textbf{Szűrés query-vel}: \texttt{/users?role=admin}
      \item \textbf{Ne igék}: \texttt{POST /users} $\checkmark$, \texttt{/createUser} $\times$
    \end{enumerate}
  \end{alertblock}
\end{frame}

\begin{frame}{Összefoglalás - Routing}
  \begin{itemize}
    \item Routing = kérések irányítása végpontokra
    \item Route paraméterek: \texttt{/users/:id} $\rightarrow$ \texttt{req.params.id}
    \item Query paraméterek: \texttt{/users?page=1} $\rightarrow$ \texttt{req.query.page}
    \item Express Router: moduláris route szervezés
    \item Controller-ek: logika szétválasztása
    \item Middleware: route-specifikus middleware-ek
    \item Verziókezelés: /api/v1, /api/v2
  \end{itemize}
  
  \vspace{0.5cm}
  
\end{frame}
