Skip to content

HTTP, APIs und Webservices

REST-APIs nutzen, Daten abrufen und externe Systeme automatisieren.

Moderne IT-Infrastrukturen bestehen aus einer Vielzahl von Diensten, die über HTTP-Schnittstellen miteinander kommunizieren. Cloud-Anbieter, Monitoring-Systeme, Ticket-Systeme, Container-Plattformen und viele weitere Werkzeuge stellen REST-APIs zur Verfügung, über die Informationen abgerufen oder Aktionen ausgelöst werden können.

Für Systemadministratoren und DevOps Engineers gehört der Umgang mit APIs mittlerweile zum Alltag. Serverinformationen werden aus Inventar- Systemen geladen, Monitoring-Daten abgefragt, Deployments gestartet oder Konfigurationen automatisiert verwaltet.

Python bietet mit Bibliotheken wie requests eine einfache und leistungsfähige Möglichkeit, HTTP-Anfragen auszuführen und Antworten weiterzuverarbeiten. In Kombination mit JSON lassen sich dadurch zahlreiche Aufgaben automatisieren, die sonst manuell über Weboberflächen erledigt werden müssten.

In diesem Kapitel lernen Sie die wichtigsten Grundlagen für die Arbeit mit HTTP, REST-APIs und Webservices kennen und setzen diese in praxisnahen Beispielen um.

HTTP-Anfragen mit requests

HTTP-Anfragen mit requests: Grundlagen und Praxis

Das Python-Modul requests ist das bevorzugte Werkzeug, um HTTP-Anfragen einfach und lesbar auszuführen. Es abstrahiert die Komplexität von Verbindungen, Headern und Datenformaten und ist damit ideal für Automatisierungsskripte in der Systemadministration.

Installation

requests ist nicht Teil der Standardbibliothek, lässt sich aber mit einem einfachen Befehl installieren:

pip install requests

Eine einfache GET-Anfrage

GET-Anfragen sind die Grundlage, um Informationen von Webservern oder APIs abzurufen. Im Vergleich zu Shell-Tools wie curl bietet requests eine native Python-Schnittstelle, die das Parsen und Weiterverarbeiten der Antwort erleichtert.

import requests

url = "https://api.github.com/repos/psf/requests"
response = requests.get(url)

print(f"Statuscode: {response.status_code}")
print(f"Content-Type: {response.headers['Content-Type']}")
print("Repository Name:", response.json()["name"])

Hier wird eine API von GitHub abgefragt, um Informationen über das requests-Repository zu erhalten. Die Antwort wird als JSON dekodiert und ein bestimmtes Feld ausgegeben.

POST-Anfragen mit Daten

import requests

url = "https://httpbin.org/post"
data = {"hostname": "server01", "action": "restart"}

response = requests.post(url, json=data)

print(f"Statuscode: {response.status_code}")
print("Antwort JSON:", response.json())

Im Beispiel wird ein JSON-Objekt an einen Test-Endpunkt gesendet, der die empfangenen Daten zurückgibt. So lassen sich API-Interaktionen simulieren.

Wichtige Parameter und Best Practices

  • Timeout setzen: Vermeiden Sie, dass Ihr Skript bei Netzwerkproblemen ewig wartet.
response = requests.get(url, timeout=5)  # 5 Sekunden Timeout
  • Fehlerbehandlung: Prüfen Sie immer den Statuscode, um unerwartete Fehler zu erkennen.
if response.ok:
    print("Erfolgreich abgefragt")
else:
    print(f"Fehler: {response.status_code}")
  • Header anpassen: Manche APIs erwarten spezifische Header, z.B. einen User-Agent.
headers = {"User-Agent": "AdminScript/1.0"}
response = requests.get(url, headers=headers)

Vergleich mit Shell-Skripten

Während curl oder wget schnell und praktisch sind, bietet requests in Python folgende Vorteile:

  • Direkte Verarbeitung der Antwort (JSON, Text, Binärdaten) ohne Zwischenspeicherung
  • Bessere Fehlerbehandlung und Logging
  • Integration in größere Automatisierungsskripte

Zusammenfassung

Mit requests können Sie HTTP-Anfragen in Python einfach und übersichtlich ausführen. Dies ist die Basis, um REST-APIs abzufragen, Automatisierungsskripte zu schreiben oder Monitoring-Daten zu sammeln. Im nächsten Abschnitt lernen Sie, wie Sie die erhaltenen JSON-Daten sinnvoll weiterverarbeiten.

REST-APIs verwenden

REST-APIs verstehen und nutzen

REST-APIs sind Schnittstellen, über die Systeme standardisiert Daten austauschen. Für Administratoren und DevOps-Teams sind sie ein mächtiges Werkzeug, um Infrastruktur, Monitoring oder Cloud-Dienste automatisiert abzufragen und zu steuern. Die Kommunikation erfolgt meist über HTTP, und die Daten werden häufig im JSON-Format übertragen.

JSON-Daten mit Python verarbeiten

JSON (JavaScript Object Notation) ist ein leichtgewichtiges, textbasiertes Datenformat. Python bietet mit dem Modul json eine einfache Möglichkeit, JSON-Daten in Python-Datenstrukturen umzuwandeln und umgekehrt.

import json

json_text = '{"status": "ok", "uptime": 12345}'
# JSON-String in Python-Dictionary umwandeln
data = json.loads(json_text)
print(data["status"])  # Ausgabe: ok

# Python-Datenstruktur zurück in JSON-String
json_str = json.dumps(data, indent=2)
print(json_str)

Beispiel: Status einer Monitoring-API abfragen

Viele Monitoring-Systeme wie Prometheus oder Zabbix bieten REST-APIs zur Abfrage von Systemmetriken. Hier ein Beispiel, wie man mit requests eine Statusabfrage durchführt und die JSON-Antwort auswertet.

import requests

url = "https://monitoring.example.com/api/v1/status"
response = requests.get(url)

if response.status_code == 200:
    status_data = response.json()  # JSON-Antwort direkt als Python-Daten
    print(f"Systemstatus: {status_data['status']}")
    print(f"Uptime: {status_data['uptime']} Sekunden")
else:
    print(f"Fehler beim Abrufen: {response.status_code}")

Schritt-für-Schritt: API-Daten sinnvoll auswerten

  1. HTTP-Status prüfen: Nur bei 200 (OK) die Antwort weiterverarbeiten.
  2. JSON parsen: Mit response.json() erhält man ein Python-Dictionary.
  3. Datenzugriff: Über Schlüssel auf relevante Werte zugreifen.
  4. Fehlerbehandlung: Fehlende oder unerwartete Daten abfangen.

Praxisfall: Serverinventar aus einer Cloud-API

Viele Cloud-Anbieter stellen REST-APIs bereit, um virtuelle Maschinen oder Container aufzulisten. Beispiel mit fiktiver API:

import requests

api_url = "https://cloud.example.com/v1/servers"
headers = {"Authorization": "Bearer DEIN_API_TOKEN"}

response = requests.get(api_url, headers=headers)
response.raise_for_status()  # Bei Fehlern Ausnahme auslösen

servers = response.json().get("servers", [])

for server in servers:
    print(f"Name: {server['name']}, Status: {server['status']}, IP: {server.get('ip', 'keine IP')}")

Warum Python statt Shell-Skripte?

Shell-Skripte können HTTP-Anfragen mit curl ausführen, aber JSON-Auswertung ist kompliziert und fehleranfällig. Python ermöglicht:

  • Einfaches Parsen und Navigieren in komplexen JSON-Strukturen
  • Klare Fehlerbehandlung
  • Wiederverwendbare Funktionen und Module

Damit wird die Automatisierung robuster und leichter wartbar.

Zusammenfassung

  • REST-APIs liefern Daten meist als JSON, das sich mit Python einfach verarbeiten lässt.
  • requests und json sind die zentralen Module für API-Kommunikation und Datenverarbeitung.
  • Praktische Beispiele aus Monitoring und Cloud zeigen typische Anwendungsfälle.
  • Python erleichtert das Auswerten und Automatisieren von API-Daten gegenüber klassischen Shell-Methoden.

Authentifizierung und API-Tokens

API-Keys sicher verwalten mit python-dotenv

API-Keys und Tokens sind sensible Zugangsdaten, die nicht im Klartext im Quellcode stehen sollten. Eine bewährte Methode ist das Auslagern dieser Werte in Umgebungsvariablen. Das Python-Paket python-dotenv ermöglicht es, Umgebungsvariablen aus einer .env-Datei zu laden, die nicht ins Versionskontrollsystem aufgenommen wird.

Ein Beispiel .env-Datei:

API_KEY=dein_geheimer_api_key
BEARER_TOKEN=dein_bearer_token

Diese Datei liegt im Projektverzeichnis, wird aber z.B. in .gitignore eingetragen.

Beispiel: API-Key für eine GET-Anfrage verwenden

import os
from dotenv import load_dotenv
import requests

load_dotenv()  # lädt Variablen aus .env

api_key = os.getenv('API_KEY')

url = 'https://api.monitoring.example.com/v1/servers'
headers = {'Authorization': f'Api-Key {api_key}'}

response = requests.get(url, headers=headers)
response.raise_for_status()  # Fehler sofort erkennen

data = response.json()
print(f"Gefundene Server: {len(data['servers'])}")

Hier wird der API-Key im Header übergeben. Viele APIs erwarten diesen Header, um den Client zu authentifizieren.

Bearer-Token für OAuth-geschützte APIs

Bearer-Tokens sind oft Teil von OAuth2-Authentifizierungen. Sie werden im Header als Authorization: Bearer <token> gesendet.

bearer_token = os.getenv('BEARER_TOKEN')

headers = {'Authorization': f'Bearer {bearer_token}'}

url = 'https://api.cloudprovider.example.com/v2/instances'
response = requests.get(url, headers=headers)
response.raise_for_status()

instances = response.json()
print(f"Instanzen: {len(instances['items'])}")

Grundlegende HTTP-Authentifizierung (Basic Auth)

Manche APIs oder interne Dienste nutzen Basic Auth, bei der Benutzername und Passwort in der Anfrage kodiert werden.

from requests.auth import HTTPBasicAuth

username = os.getenv('API_USER')
password = os.getenv('API_PASS')

url = 'https://internal-api.example.com/status'
response = requests.get(url, auth=HTTPBasicAuth(username, password))
response.raise_for_status()

status = response.json()
print(f"Systemstatus: {status['state']}")

Warum nicht einfach im Code?

  • Sicherheit: API-Keys im Code landen oft in Versionskontrolle und können so öffentlich werden.
  • Flexibilität: Verschiedene Umgebungen (Test, Produktion) können unterschiedliche Schlüssel verwenden, ohne Codeänderung.

Tipps für den Alltag

  • .env-Dateien niemals ins Git-Repository einchecken.
  • Verwenden Sie für Produktionssysteme Umgebungsvariablen des Betriebssystems oder Secrets-Management-Tools.
  • Prüfen Sie die API-Dokumentation genau: Manche APIs erwarten den Key als URL-Parameter, andere im Header.
  • Fehlerbehandlung: Prüfen Sie immer den HTTP-Status und behandeln Sie Fehlermeldungen sinnvoll.

Mit diesen Grundlagen können Sie API-Authentifizierungen sicher und flexibel in Ihren Python-Skripten umsetzen, was die Automatisierung von Infrastruktur- und Monitoring-Aufgaben deutlich erleichtert.

Dateien herunterladen

Dateien mit requests herunterladen

Für die Automatisierung von Downloads ist das Modul requests ideal, da es HTTP-Anfragen einfach handhabbar macht. Besonders bei großen Dateien ist es wichtig, den Download in kleinen Stücken (Chunks) zu verarbeiten, um Speicher zu schonen.

import requests

url = 'https://example.com/logs/server-log-2024-06-01.log'
local_path = '/var/log/remote/server-log-2024-06-01.log'

with requests.get(url, stream=True) as response:
    response.raise_for_status()  # Fehler prüfen
    with open(local_path, 'wb') as file:
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:  # Filtert Keep-Alive-Chunks
                file.write(chunk)

Warum stream=True? Ohne Streaming würde requests die gesamte Datei im Speicher halten. Bei großen Dateien kann das zu Speicherproblemen führen. Mit Streaming liest man die Datei Stück für Stück und schreibt sie direkt auf die Festplatte.

Fortschrittsanzeige für große Downloads

Für längere Downloads ist eine Fortschrittsanzeige hilfreich, um den Status zu überwachen. Dazu kann man die Content-Length aus dem Header nutzen:

import requests
from tqdm import tqdm  # Fortschrittsbalken (muss ggf. installiert werden)

url = 'https://example.com/backup/infra-backup.tar.gz'
local_path = '/backups/infra-backup.tar.gz'

with requests.get(url, stream=True) as response:
    response.raise_for_status()
    total_size = int(response.headers.get('content-length', 0))
    chunk_size = 8192
    with open(local_path, 'wb') as file, tqdm(
        total=total_size, unit='B', unit_scale=True, desc='Download'
    ) as progress:
        for chunk in response.iter_content(chunk_size=chunk_size):
            if chunk:
                file.write(chunk)
                progress.update(len(chunk))

Hinweis: tqdm ist ein externes Paket, das mit pip install tqdm installiert werden kann. Es erleichtert die Anzeige von Fortschrittsbalken in der Konsole.

Umgang mit Authentifizierung bei Downloads

Viele Infrastruktur-APIs oder Cloud-Anbieter schützen Download-URLs mit Authentifizierung, z. B. API-Tokens oder Basic Auth. requests unterstützt beides:

# Beispiel mit Bearer-Token
headers = {'Authorization': 'Bearer <API_TOKEN>'}

with requests.get(url, headers=headers, stream=True) as response:
    response.raise_for_status()
    # Datei speichern wie oben

Best Practices

  • Nutze stream=True bei großen Dateien, um Speicher zu sparen.
  • Prüfe HTTP-Statuscodes mit raise_for_status().
  • Verwende eine Fortschrittsanzeige bei langen Downloads.
  • Speichere Dateien in passenden Verzeichnissen mit aussagekräftigen Namen.
  • Achte auf sichere Handhabung von Authentifizierungsdaten (siehe Kapitel zu API-Tokens).

Zusammenfassung

Das Herunterladen von Dateien mit Python ist dank requests unkompliziert und leistungsfähig. Für Systemadministratoren und DevOps-Profis ermöglicht es, Backups, Logs oder Konfigurationsdateien automatisiert und effizient zu sichern – oft mit besserer Kontrolle und Fehlerbehandlung als klassische Shell-Tools.

Automatisierung mit APIs

APIs als Werkzeug für Automatisierung

APIs sind in modernen IT-Umgebungen unverzichtbar, um Infrastruktur, Monitoring und Cloud-Dienste programmatisch zu steuern. Statt wiederkehrende manuelle Schritte in Webinterfaces oder CLI-Tools auszuführen, lassen sich administrative Aufgaben mit Python und HTTP-APIs automatisieren. Das spart Zeit, reduziert Fehler und ermöglicht komplexe Workflows.

Beispiel: Serverstatus per API abfragen

Viele Monitoring-Systeme wie Prometheus, Zabbix oder Cloud-Dienste bieten REST-APIs, um Statusinformationen abzurufen. Ein typischer Anwendungsfall ist das automatisierte Auslesen von Servermetriken oder Alarmen.

import requests

# Beispiel-URL eines Monitoring-API-Endpunkts
url = "https://monitoring.example.com/api/v1/alerts"

# API-Key für Authentifizierung (z.B. aus Umgebungsvariablen laden)
api_key = "DEIN_API_KEY"

headers = {"Authorization": f"Bearer {api_key}"}

response = requests.get(url, headers=headers)
response.raise_for_status()  # Fehler sofort erkennen

alerts = response.json()  # JSON-Antwort in Python-Daten umwandeln

# Beispiel: Alle kritischen Alarme ausgeben
for alert in alerts.get("data", []):
    if alert.get("severity") == "critical":
        print(f"Kritischer Alarm: {alert['message']} auf {alert['host']}")

Automatisierte Konfigurationsänderungen

Viele Systeme erlauben Änderungen via API, z. B. das Anpassen von Firewall-Regeln oder das Erstellen neuer Cloud-Ressourcen. Hierfür sind POST- oder PUT-Anfragen üblich.

import requests
import json

url = "https://firewall.example.com/api/v1/rules"
api_key = "DEIN_API_KEY"

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
}

# Neue Firewall-Regel definieren
rule = {
    "source": "10.0.0.0/24",
    "destination": "0.0.0.0/0",
    "port": 22,
    "action": "allow"
}

response = requests.post(url, headers=headers, data=json.dumps(rule))
response.raise_for_status()
print("Firewall-Regel erfolgreich hinzugefügt.")

Vorteile von Python gegenüber Shell-Skripten

  • Bessere Fehlerbehandlung: requests.raise_for_status() und Ausnahmen helfen, Probleme früh zu erkennen.
  • Strukturierte Daten: JSON-Antworten lassen sich direkt in Python-Objekte umwandeln und leicht verarbeiten.
  • Wiederverwendbarkeit: Funktionen und Module erleichtern das Organisieren größerer Automatisierungsprojekte.
  • Plattformunabhängigkeit: Python-Skripte laufen auf Windows, Linux und macOS ohne Anpassungen.

Best Practices

  • API-Keys sicher speichern: Verwenden Sie Umgebungsvariablen oder .env-Dateien, z. B. mit python-dotenv, um sensible Daten nicht im Code zu hinterlegen.
  • Timeouts setzen: Vermeiden Sie hängende Anfragen mit requests.get(url, timeout=10).
  • Statuscodes prüfen: Nutzen Sie raise_for_status() oder prüfen Sie response.status_code explizit.
  • Logging einbauen: Protokollieren Sie API-Aufrufe und Antworten für Fehleranalyse.

Zusammenfassung

Mit Python und HTTP-APIs lassen sich administrative Abläufe effizient automatisieren. Das Abrufen von Statusdaten, das Anpassen von Konfigurationen oder das Auslösen von Aktionen über Web-APIs reduziert manuellen Aufwand und erhöht die Zuverlässigkeit. Die Kombination aus klarer Syntax, guter Fehlerbehandlung und JSON-Verarbeitung macht Python zum idealen Werkzeug für DevOps- und Infrastrukturaufgaben.