Was ist REST?
REST (Representational State Transfer) ist ein Architekturstil für den Aufbau verteilter Systeme, der 2000 von Roy Fielding in seiner Doktorarbeit vorgeschlagen wurde. REST ist kein Protokoll oder Standard, sondern eine Reihe von Prinzipien und Einschränkungen, die ein System befolgen muss.
API (Application Programming Interface) ist eine Schnittstelle für die Interaktion zwischen Programmen. REST API ist dementsprechend eine API, die nach den REST-Prinzipien aufgebaut ist.
Einfach ausgedrückt, ist eine REST-API eine Möglichkeit, die Kommunikation zwischen einem Client und einem Server über ein HTTP-Protokoll zu organisieren, bei dem jede Ressource (Daten) eine eindeutige Adresse (URL) hat und über Standard-HTTP-Methoden aufgerufen werden kann.
Grundprinzipien von REST
REST basiert auf sechs Schlüsselprinzipien, die die Systemarchitektur definieren.
1. Client-Server
Die Architektur ist in einen Client, der Anfragen sendet, und einen Server, der diese Anfragen verarbeitet und Antworten zurückgibt, unterteilt. Diese Trennung ermöglicht es dem Client und dem Server, sich unabhängig voneinander zu entwickeln.
2. Stateless (Ohne Speicherung des Status)
Jede Anfrage vom Client an den Server muss alle Informationen enthalten, die zum Verständnis und zur Bearbeitung der Anfrage erforderlich sind. Der Server speichert keine Informationen über den Status des Clients zwischen den Anfragen. Wenn eine Authentifizierung erforderlich ist, wird das Token mit jeder Anfrage übertragen.
3. Cacheable (Zwischenspeicherbarkeit)
Serverantworten müssen explizit angeben, ob sie zwischengespeichert werden können. Dies verbessert die Systemleistung, indem die Anzahl der Serveranfragen reduziert wird.
4. Uniform Interface (Einheitliche Schnittstelle)
Dies ist ein zentrales REST-Prinzip, das die Systemarchitektur vereinfacht. Es umfasst vier Aspekte: Ressourcenidentifikation über URI, Ressourcenmanipulation über Darstellungen, selbsterklärende Nachrichten und HATEOAS (Hypermedia als Anwendungsstatus-Engine).
5. Layered System (Schichtsystem)
Der Client kann nicht feststellen, ob er direkt mit dem Endserver oder mit einem Zwischenknoten verbunden ist. Auf diese Weise können Sie Load Balancer, Caches und andere Zwischenkomponenten hinzufügen, ohne den Clientcode zu ändern.
6. Code on Demand (Code auf Anfrage)
Dies ist das einzige optionale Prinzip. Server können die Funktionalität des Clients vorübergehend erweitern, indem sie ausführbaren Code wie JavaScript übertragen.
HTTP-Methoden in der REST-API
Die REST-API verwendet Standard-HTTP-Methoden, um Operationen mit Ressourcen auszuführen. Jede Methode hat einen bestimmten Zweck:
GET — Daten abrufen
Die GET-Methode wird verwendet, um Daten vom Server zu lesen. Es sollte den Zustand der Ressource nicht ändern.
// Liste aller Benutzer abrufen
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data));
// Einen bestimmten Benutzer erhalten
fetch('https://api.example.com/users/123')
.then(response => response.json())
.then(data => console.log(data));POST — Neue Ressource erstellen
POST wird verwendet, um neue Ressourcen auf dem Server zu erstellen.
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Ivan Petrov',
email: 'ivan@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));PUT — Vollständige Ressourcenaktualisierung
PUT ersetzt die vorhandene Ressource vollständig durch neue Daten.
fetch('https://api.example.com/users/123', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Ivan Petrov',
email: 'newemail@example.com',
age: 30
})
})
.then(response => response.json())
.then(data => console.log(data));PATCH — Teilaktualisierung der Ressource
PATCH aktualisiert nur die angegebenen Felder der Ressource.
fetch('https://api.example.com/users/123', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'newemail@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));DELETE — Löschen einer Ressource
DELETE wird verwendet, um eine Ressource vom Server zu löschen.
fetch('https://api.example.com/users/123', {
method: 'DELETE'
})
.then(response => {
if (response.ok) {
console.log('User removed');
}
});
REST-API-Struktur
Die korrekte Struktur der URL in der REST-API ist entscheidend für das Verständnis und die Verwendung der API.
Ressourcen und Sammlungen
Bei REST ist alles eine Ressource. Ressourcen werden in Sammlungen gruppiert:
GET /users - Получить список пользователей (коллекция)
GET /users/123 - Получить конкретного пользователя (ресурс)
POST /users - Создать нового пользователя
PUT /users/123 - Обновить пользователя
DELETE /users/123 - Удалить пользователяEingesetzte Ressourcen
Für verknüpfte Ressourcen werden eingebettete URLs verwendet:
GET /users/123/posts - Все посты пользователя
GET /users/123/posts/456 - Конкретный пост пользователя
POST /users/123/posts - Создать пост для пользователя
DELETE /users/123/posts/456 - Удалить пост пользователяFiltern und Sortieren
Verwenden Sie Abfrageparameter zum Filtern, Sortieren und Paginieren:
GET /users?role=admin - Фильтрация по роли
GET /users?sort=name&order=asc - Сортировка по имени
GET /users?page=2&limit=20 - Пагинация
GET /users?search=иван - ПоискHTTP-Antwortstatus
Die REST-API verwendet Standard-HTTP-Statuscodes, um den Client über das Ergebnis der Anfrage zu informieren.
Erfolgreiche Antworten (2xx)
200 OK — Anfrage erfolgreich abgeschlossen (für GET, PUT, PATCH)
201 Created — Ressource erfolgreich erstellt (für POST)
204 No Content — Die Anfrage wurde erfolgreich ausgeführt, aber es gibt keinen Inhalt zum Zurückgeben (häufig für DELETE)
Client-Fehler (4xx)
400 Bad Request — ungültige Anfrage (z. B. ungültiges JSON)
401 Unauthorized - Authentifizierung erforderlich
403 Forbidden — Zugriff verweigert (Authentifizierung vorhanden, aber keine Rechte)
404 Not Found — Ressource nicht gefunden
409 Conflict — Konflikt (z. B. ein Benutzer mit dieser E-Mail-Adresse existiert bereits)
422 Unprocessable Entity — Validierung nicht bestanden
Serverfehler (5xx)
500 Internal Server Error — interner Serverfehler
503 Service Unavailable — Service vorübergehend nicht verfügbar
Datenformat
REST-APIs arbeiten normalerweise mit JSON (JavaScript Object Notation), obwohl auch XML verwendet werden kann.
Beispiel für eine JSON-Antwort
{
"id": 123,
"name": "Ivan Petrov",
"email": "ivan@example.com",
"created_at": "2024-01-15T10:30:00Z",
"posts": [
{
"id": 1,
"title": "First post",
"published": true
}
]
}Beispiel für einen JSON-Fehler
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Data validation error",
"details": [
{
"field": "email",
"message": "Incorrect email format"
}
]
}
}Authentifizierung und Sicherheit
REST-API erfordert häufig eine Authentifizierung, um auf sichere Ressourcen zugreifen zu können.
JWT (JSON Web Token)
Die beliebteste Authentifizierungsmethode für REST-APIs:
// Token beim Einloggen erhalten
fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'user@example.com',
password: 'password123'
})
})
.then(response => response.json())
.then(data => {
// Token speichern
localStorage.setItem('token', data.token);
});
// Verwendung eines Tokens für sichere Anfragen
fetch('https://api.example.com/users/me', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
})
.then(response => response.json())
.then(data => console.log(data));API Keys
Eine einfache Methode für serviceorientierte APIs:
fetch('https://api.example.com/data', {
headers: {
'X-API-Key': 'your-secret-key'
}
})
.then(response => response.json())
.then(data => console.log(data));API-Versionierung
Wenn sich die API weiterentwickelt, ist es wichtig, die Abwärtskompatibilität beizubehalten. Es gibt verschiedene Ansätze für die Versionskontrolle:
URL Path Versioning
https://api.example.com/v1/users
https://api.example.com/v2/usersHeader Versioning
fetch('https://api.example.com/users', {
headers: {
'Accept': 'application/vnd.example.v2+json'
}
})Query Parameter Versioning
https://api.example.com/users?version=2
Praktisches Beispiel: Erstellen einer einfachen REST-API in Node.js
Erstellen wir eine einfache REST-API zum Verwalten der Aufgabenliste.
const express = require('express');
const app = express();
app.use(express.json());
// Temporärer Datenspeicher
let tasks = [
{ id: 1, title: 'Explore the REST API', completed: false },
{ id: 2, title: 'Create a project', completed: false }
];
let nextId = 3;
// GET - Alle Aufgaben abrufen
app.get('/api/tasks', (req, res) => {
res.json(tasks);
});
// GET - Eine bestimmte Aufgabe erhalten
app.get('/api/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) {
return res.status(404).json({
error: 'Task not found'
});
}
res.json(task);
});
// POST - Neue Aufgabe erstellen
app.post('/api/tasks', (req, res) => {
const { title } = req.body;
if (!title) {
return res.status(400).json({
error: 'Task name is required'
});
}
const newTask = {
id: nextId++,
title,
completed: false
};
tasks.push(newTask);
res.status(201).json(newTask);
});
// PUT - Aufgabe aktualisieren
app.put('/api/tasks/:id', (req, res) => {
const taskIndex = tasks.findIndex(t => t.id === parseInt(req.params.id));
if (taskIndex === -1) {
return res.status(404).json({
error: 'Task not found'
});
}
const { title, completed } = req.body;
tasks[taskIndex] = {
id: parseInt(req.params.id),
title: title || tasks[taskIndex].title,
completed: completed !== undefined ? completed : tasks[taskIndex].completed
};
res.json(tasks[taskIndex]);
});
// DELETE - Aufgabe löschen
app.delete('/api/tasks/:id', (req, res) => {
const taskIndex = tasks.findIndex(t => t.id === parseInt(req.params.id));
if (taskIndex === -1) {
return res.status(404).json({
error: 'Task not found'
});
}
tasks.splice(taskIndex, 1);
res.status(204).send();
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Best Practices bei der Entwicklung von REST-APIs
1. Verwenden Sie Substantive, keine Verben
Gut:
GET /users
POST /usersSchlecht:
GET /getUsers
POST /createUser2. Verwenden Sie den Plural für Sammlungen
GET /users (а не /user)
GET /posts (а не /post)3. Geben Sie die richtigen HTTP-Codes zurück
Geben Sie nicht 200 OK für alle Antworten zurück. Verwenden Sie geeignete Statuscodes.
4. Stellen Sie detaillierte Fehlermeldungen sicher
{
"error": {
"code": "INVALID_EMAIL",
"message": "Invalid email address provided",
"field": "email",
"value": "invalid-email"
}
}5. Verwenden Sie die Paginierung für große Sammlungen
app.get('/api/users', (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
const results = {
data: users.slice(startIndex, endIndex),
pagination: {
page,
limit,
total: users.length,
totalPages: Math.ceil(users.length / limit)
}
};
res.json(results);
});6. Dokumentieren Sie Ihre API
Verwenden Sie Tools wie Swagger/OpenAPI, um die API zu dokumentieren.
7. Verwenden Sie HTTPS
Verwenden Sie immer HTTPS für die Datenübertragung, insbesondere wenn Sie mit sensiblen Informationen arbeiten.
8. Implementieren Sie Rate Limiting
Begrenzen Sie die Anzahl der Anfragen von einem Kunden, um Missbrauch zu verhindern.
REST vs GraphQL vs gRPC
REST ist nicht die einzige Möglichkeit, eine API zu erstellen. Hier ist ein kurzer Vergleich:
REST eignet sich für die meisten Standard-Webanwendungen, ist einfach zu verstehen und zu implementieren, hat eine breite Unterstützung und ein hervorragendes Caching.
GraphQL nützlich, wenn der Kunde Flexibilität bei der Auswahl der Daten benötigt, ermöglicht es, alles in einer Abfrage zu erhalten und ein Über- oder Unterabrufen von Daten zu vermeiden.
gRPC optimal für Microservice-Architektur, Hochleistungssysteme und interne APIs, verwendet ein binäres Protokoll und ist schneller als REST.
Tools für die Arbeit mit der REST-API
API-Test
Postman — ein beliebtes API-Testwerkzeug mit grafischer Oberfläche
Insomnia – Alternative zu Postman mit minimalistischer Oberfläche
curl — Konsolenprogramm für HTTP-Anfragen
# Beispiel für die Verwendung von curl
curl -X GET https://api.example.com/users
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"Ivan","email":"ivan@example.com"}'Client-Bibliotheken
JavaScript/TypeScript:
Fetch API (eingebettet)
Axios
Got
Python:
requests
httpx
PHP:
Guzzle
cURL
Befund
REST API ist eine grundlegende Technologie der modernen Webentwicklung, die eine einfache und standardisierte Möglichkeit der Interaktion zwischen Client und Server bietet. Wenn Sie die REST-Prinzipien verstehen, HTTP-Methoden und Statuscodes richtig verwenden und Best Practices befolgen, können Sie qualitativ hochwertige, skalierbare und leicht zu wartende APIs erstellen.
Beginnen Sie mit einfachen Projekten, fügen Sie nach und nach Komplexität hinzu und vergessen Sie nicht die Dokumentation und das Testen. REST API ist eine Fähigkeit, die noch viele Jahre relevant bleiben und Ihnen die Türen zur Welt der modernen Entwicklung öffnen wird.
Treten Sie der Bildungsplattform bei Kodik, wo Sie strukturierte Kurse in JavaScript, Node.js, Python und anderen modernen Technologien finden.
Unsere freundliche Entwickler-Community in Telegram ist immer bereit, bei Fragen zu helfen, Erfahrungen zu teilen und Sie auf Ihrem Weg zum professionellen Programmierer zu unterstützen!
