Menu
CoddyTech

Hata Yönetimi

Coddy'nin Node.js Journey'sinin Express Temelleri bölümünün bir parçası. Ders 15 / 20.

Bir rota hata verdiğinde Express, JSON olmayan ve size yönelik ayrıntıları gösteren kendi hata sayfasıyla yanıt verir.

app.get('/api/fines/:member', (req, res) => {
    throw new Error('Fines database is down');
});

app.use((err, req, res, next) => {
    console.error(err);
    res.status(500).json({ error: 'Try again later' });
});

Dört argüman alan bir ara yazılım, (err, req, res, next), bir hata işleyicisidir. Express argümanları sayar: üç argümanlı olan sıradan bir ara yazılımdır ve hatalar bunu atlar. Bir rota hata verdiğinde Express, sıradan ara yazılımları atlar ve hata işleyicisini hatayla birlikte çağırır. Bunu en sona, 404 işleyicisinden sonra ekleyin. Ayrıntıları kendiniz için günlüğe kaydedin; istemciye kısa bir mesaj gönderin.

Hatalı bir ?by= ziyaretçinin hatasıdır, bu yüzden yine 400 yanıtı alır. Hata ise ziyaretçinin düzeltemeyeceği bir durum içindir; örneğin porsiyon sayısı belirtilmeden kaydedilmiş bir tarif gibi.

challenge icon

Görev

Kolay
  • GET /api/recipes/:id/scale?by=2 yanıtta { "title", "servings" } döndürür; porsiyon sayısı çarpılır.
  • Pozitif sayı olmayan bir katsayı: 400 ve { "error": "Scale by a positive number" }.
  • servings değeri olmayan bir tarif Recipe <id> has no servings hatasını fırlatır.
  • Bir hata işleyicisi hatayı günlüğe kaydeder ve 500 ile { "error": "Something went wrong" } döndürür.

?by=2 ve ?by=lots isteklerini gönder. Ardından { "title": "Toast" } değerini /api/recipes adresine gönder ve 5 numaralı tarifi ölçeklendir.

Kendin dene

import express from 'express';
import { randomUUID } from 'node:crypto';
import { recipes } from './data.js';

const app = express();

app.use((req, res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
});

app.use((req, res, next) => {
    res.set('X-Request-Id', randomUUID());
    next();
});

app.use(express.json());

app.use(express.static('public'));

const escapeHtml = (text) =>
    text
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;');

app.get('/', (req, res) => {
    const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
    res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});

// type('text') düz metin gönderir, bu nedenle her başlık ayrı bir satırda görünür.
app.get('/recipes', (req, res) => {
    const { tag } = req.query;
    const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
    res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});

app.get('/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).send('No such recipe');
        return;
    }
    res.send(recipe.title);
});

app.get('/api/recipes', (req, res) => {
    res.json(recipes);
});

app.get('/api/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

app.post('/api/recipes', (req, res) => {
    const { title, tags } = req.body;
    if (!title) {
        res.status(400).json({ error: 'A recipe needs a title' });
        return;
    }
    const recipe = { id: recipes.length + 1, title, tags: tags ?? [] };
    recipes.push(recipe);
    res.status(201).json(recipe);
});

app.get('/about', (req, res) => {
    res.send('Recipe Box collects family recipes.');
});

app.get('/menu', (req, res) => {
    res.redirect(301, '/recipes');
});

app.get('/menu/:id', (req, res) => {
    res.redirect(301, `/recipes/${req.params.id}`);
});

app.use((req, res) => {
    if (req.path.startsWith('/api/')) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    res.status(404).send('<h1>Page not found</h1><p><a href="/">Back to Recipe Box</a></p>');
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Express Temelleri bölümündeki tüm dersler