Files

5.3 KiB

6.3 Backend-Entwicklung

Server-Grundlagen

Client-Server-Architektur

Webanwendung - Architektur
┌─────────────┐      HTTP       ┌─────────────┐
│   Browser   │ ◄──────────────►│   Server    │
│  (Frontend) │                │  (Backend)  │
└─────────────┘                └──────┬──────┘
                                      │
                                ┌─────┴─────┐
                                │  Datenbank │
                                └───────────┘

Node.js

Grundlagen

// Einfacher Server
const http = require('http');

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>Hallo Welt!</h1>');
});

server.listen(3000, () => {
    console.log('Server läuft auf Port 3000');
});

Express.js

const express = require('express');
const app = express();

// Middleware
app.use(express.json());

// GET-Route
app.get('/api/benutzer', (req, res) => {
    res.json([
        { id: 1, name: 'Max' },
        { id: 2, name: 'Anna' }
    ]);
});

// POST-Route
app.post('/api/benutzer', (req, res) => {
    const neuerBenutzer = req.body;
    // Speichern...
    res.status(201).json(neuerBenutzer);
});

app.listen(3000);

REST-API

REST-Prinzipien

REST - Grundsätze
├── Ressourcen-orientiert (Nomen)
├── Stateless (keine Session)
├── Einheitliche Schnittstelle
├── Client-Server-Trennung
└── Cache-fähig

HTTP-Methoden

Methode CRUD Beschreibung
GET Read Daten abrufen
POST Create Daten erstellen
PUT Update Daten vollständig ersetzen
PATCH Update Daten teilweise ändern
DELETE Delete Daten löschen

API-Endpunkte

Beispiel: Benutzer-Ressource

GET    /api/benutzer         → Alle Benutzer
GET    /api/benutzer/:id     → Ein Benutzer
POST   /api/benutzer         → Benutzer erstellen
PUT    /api/benutzer/:id     → Benutzer ersetzen
PATCH  /api/benutzer/:id     → Benutzer ändern
DELETE /api/benutzer/:id     → Benutzer löschen

Response-Format

// Erfolgreich (200 OK)
{
    "status": "success",
    "data": {
        "id": 1,
        "name": "Max"
    }
}

// Erfolg (201 Created)
{
    "status": "success",
    "message": "Benutzer erstellt",
    "data": {
        "id": 2
    }
}

// Fehler (400 Bad Request)
{
    "status": "error",
    "message": "Ungültige E-Mail-Adresse"
}

Datenbank-Zugriff

MySQL mit Node.js

const mysql = require('mysql2/promise');

async function main() {
    const connection = await mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: 'passwort',
        database: 'webshop'
    });

    // Daten abfragen
    const [rows] = await connection.execute(
        'SELECT * FROM benutzer WHERE id = ?',
        [1]
    );
    console.log(rows);

    await connection.end();
}

main();

MongoDB mit Node.js

const mongoose = require('mongoose');

// Verbindung
mongoose.connect('mongodb://localhost:27017/webshop');

// Schema
const benutzerSchema = new mongoose.Schema({
    name: String,
    email: { type: String, unique: true },
    alter: Number
});

const Benutzer = mongoose.model('Benutzer', benutzerSchema);

// Daten speichern
const neuerBenutzer = new Benutzer({
    name: 'Max',
    email: 'max@example.com'
});
await neuerBenutzer.save();

Session und Authentifizierung

JWT (JSON Web Token)

const jwt = require('jsonwebtoken');

// Token erstellen
function createToken(user) {
    return jwt.sign(
        { id: user.id, email: user.email },
        'geheimer-schluessel',
        { expiresIn: '24h' }
    );
}

// Token prüfen
function verifyToken(token) {
    try {
        return jwt.verify(token, 'geheimer-schluessel');
    } catch (err) {
        return null;
    }
}

// Middleware
function authenticate(req, res, next) {
    const token = req.headers.authorization?.split(' ')[1];
    const decoded = verifyToken(token);

    if (!decoded) {
        return res.status(401).json({ error: 'Nicht autorisiert' });
    }

    req.user = decoded;
    next();
}

Passwort-Hashing

const bcrypt = require('bcrypt');

// Passwort hashen
async function hashPassword(password) {
    const salt = await bcrypt.genSalt(10);
    return await bcrypt.hash(password, salt);
}

// Passwort prüfen
async function checkPassword(password, hash) {
    return await bcrypt.compare(password, hash);
}

RESTful Best Practices

Tipps

API-Design - Empfehlungen
├── Versionierung: /api/v1/...
├── Plural: /benutzer nicht /benutzer
├── Filter: /benutzer?alter=25
├── Sortierung: /benutzer?sort=name
├── Paginierung: /benutzer?page=1&limit=10
├── Fehlercodes: HTTP-Statuscodes nutzen
└── Dokumentation: OpenAPI/Swagger

Querverweise


Stand: 2024