% 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}