API8 Min. Lesezeit

Query-Parameter in REST-APIs richtig kodieren

Query-Parameter in REST-APIs müssen gemäß RFC 3986 prozentkodiert werden, um Sonderzeichen wie &, =, Leerzeichen und Unicode sicher übertragen zu können. Verwende encodeURIComponent() in JavaScript, urllib.parse.quote() in Python oder URLEncoder.encode() in Java.

Warum Query-Parameter kodiert werden müssen

Query-Strings in REST-APIs verwenden ein strukturiertes Format, bei dem Schlüssel-Wert-Paare durch & getrennt werden und Schlüssel durch = von ihren Werten getrennt sind. Enthält ein Parameterwert eines dieser Trennzeichen oder andere reservierte Zeichen wie #, + oder Leerzeichen, bricht die Struktur des Query-Strings auseinander und der Server empfängt fehlerhafte Daten.

Betrachten wir ein Beispiel: Du möchtest in einer API nach "salt & pepper" suchen. Ohne Kodierung teilt die URL /search?q=salt & pepper dem Server mit, dass es zwei Parameter gibt: q=salt und pepper (ohne Wert). Mit korrekter Kodierung überträgt /search?q=salt%20%26%20pepper hingegen korrekt einen einzigen Parameter q mit dem Wert "salt & pepper".

Über die Korrektheit hinaus verhindert eine ordnungsgemäße Kodierung auch Sicherheitslücken. Nicht kodierte Benutzereingaben in URLs können zu Injection-Angriffen, Cache Poisoning und anderen Exploits führen. Kodiere Parameterwerte daher stets, bevor du sie in URLs einfügst.

Kodierung in verschiedenen Sprachen

Jede gängige Programmiersprache stellt integrierte Funktionen zur URL-Kodierung bereit. So kodierst du Query-Parameter in den beliebtesten Sprachen korrekt.

// JavaScript
// Verwende encodeURIComponent() für einzelne Parameterwerte
const query = 'price >= 100 & category = books';
const url = 'https://api.example.com/search?q=' + encodeURIComponent(query);
// "https://api.example.com/search?q=price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// Oder verwende URLSearchParams für mehrere Parameter
const params = new URLSearchParams({
  q: 'price >= 100 & category = books',
  page: '1',
  sort: 'price'
});
const url2 = 'https://api.example.com/search?' + params.toString();
# Python
from urllib.parse import urlencode, quote

# urlencode für mehrere Parameter verwenden
params = {
    'q': 'price >= 100 & category = books',
    'page': 1,
    'sort': 'price'
}
query_string = urlencode(params)
url = f'https://api.example.com/search?{query_string}'

# quote für einen einzelnen Wert verwenden
value = quote('price >= 100 & category = books', safe='')
url = f'https://api.example.com/search?q={value}'
// Java
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

String query = "price >= 100 & category = books";
String encoded = URLEncoder.encode(query, StandardCharsets.UTF_8);
// "price+%3E%3D+100+%26+category+%3D+books"
// Hinweis: URLEncoder verwendet + für Leerzeichen (Form-Kodierung)

// Für RFC-3986-Kodierung + durch %20 ersetzen
String rfc3986 = encoded.replace("+", "%20");
String url = "https://api.example.com/search?q=" + rfc3986;
// C#
using System.Net;
using System.Web;

string query = "price >= 100 & category = books";

// Uri.EscapeDataString folgt RFC 3986
string encoded = Uri.EscapeDataString(query);
// "price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// HttpUtility.UrlEncode verwendet Form-Kodierung (+ für Leerzeichen)
string formEncoded = HttpUtility.UrlEncode(query);
// "price+%3e%3d+100+%26+category+%3d+books"
// Go
package main

import (
    "fmt"
    "net/url"
)

func main() {
    // url.QueryEscape kodiert für Query-Strings (+ für Leerzeichen)
    encoded := url.QueryEscape("price >= 100 & category = books")
    // "price+%3E%3D+100+%26+category+%3D+books"

    // url.PathEscape kodiert für Pfadsegmente (%20 für Leerzeichen)
    pathEncoded := url.PathEscape("my file name.pdf")
    // "my%20file%20name.pdf"

    // url.Values zum Aufbau von Query-Strings verwenden
    params := url.Values{}
    params.Set("q", "price >= 100 & category = books")
    params.Set("page", "1")
    queryString := params.Encode()
    fmt.Println(queryString)
}

Arrays und verschachtelte Objekte kodieren

REST-APIs müssen häufig Arrays oder verschachtelte Objekte als Query-Parameter entgegennehmen. Für die Kodierung dieser komplexen Typen gibt es keinen einheitlichen Standard, weshalb verschiedene APIs unterschiedliche Konventionen verwenden.

// Wiederholte Schlüssel (am weitesten unterstützt)
// GET /api/items?tag=javascript&tag=python&tag=go
const params = new URLSearchParams();
['javascript', 'python', 'go'].forEach(tag => params.append('tag', tag));

// Klammer-Notation (verbreitet in PHP, Rails, Express mit qs)
// GET /api/items?tags[]=javascript&tags[]=python&tags[]=go
// Muss manuell kodiert werden:
const tags = ['javascript', 'python', 'go'];
const qs = tags.map(t => 'tags[]=' + encodeURIComponent(t)).join('&');

// Kommagetrennt (einfach, aber eingeschränkt)
// GET /api/items?tags=javascript,python,go
const tagList = encodeURIComponent('javascript,python,go');

// Verschachtelte Objekte (Klammer-Notation)
// GET /api/search?filter[status]=active&filter[min_price]=10
// In Python:
params = {
    'filter[status]': 'active',
    'filter[min_price]': '10'
}

Prüfe stets die Dokumentation deiner API auf das erwartete Format. Beim Entwurf einer neuen API ist der Ansatz mit wiederholten Schlüsseln über Programmiersprachen und HTTP-Bibliotheken hinweg am portabelsten.

Best Practices für die serverseitige Dekodierung

Bei der Verarbeitung eingehender Anfragen auf der Serverseite dekodieren die meisten Web-Frameworks Query-Parameter automatisch für dich. Dennoch gibt es wichtige Aspekte, die du für eine robuste serverseitige Verarbeitung beachten solltest.

  • Die meisten Frameworks (Express, Django, Spring, ASP.NET) dekodieren Query-Parameter automatisch. Dekodiere sie nicht manuell erneut, sonst kommt es zu einer doppelten Dekodierung.
  • Validiere dekodierte Werte gegen erwartete Typen und Wertebereiche, bevor du sie verwendest.
  • Lege auf Ebene des Webservers Obergrenzen für die URL-Länge fest (üblicherweise 2048 oder 8192 Zeichen).
  • Berücksichtige den Fall, dass + je nach Content-Type entweder ein Leerzeichen oder ein wörtliches Pluszeichen bedeuten kann.
  • Protokolliere die ursprüngliche (kodierte) URL zur Fehlersuche, da dekodierte Werte in Logs irreführend sein können.
// Express.js - Parameter werden automatisch dekodiert
app.get('/search', (req, res) => {
  const query = req.query.q; // Bereits dekodiert
  // NICHT verwenden: decodeURIComponent(req.query.q)

  // Eingabe validieren
  if (typeof query !== 'string' || query.length > 200) {
    return res.status(400).json({ error: 'Invalid query parameter' });
  }

  // Den dekodierten Wert sicher verwenden
  const results = search(query);
  res.json(results);
});

Sicherheitsaspekte

Die ordnungsgemäße Kodierung von Query-Parametern ist ein zentraler Bestandteil der API-Sicherheit. Hier sind die wichtigsten Sicherheitspraktiken, die du befolgen solltest.

  • Vertraue niemals der clientseitigen Kodierung. Validiere und bereinige dekodierte Parameter stets auf dem Server, selbst wenn der Client sie korrekt kodiert hat.
  • Achte auf Double-Encoding-Angriffe. Ein Angreifer könnte bösartige Zeichen doppelt kodieren, um Eingabefilter zu umgehen, die nur einmal dekodieren. Stelle sicher, dass deine Sicherheitsfilter die vollständig dekodierten Werte sehen.
  • Verhindere Path Traversal. Kodierte Sequenzen wie %2e%2e%2f (../) in Pfadparametern können genutzt werden, um auf Dateien außerhalb des vorgesehenen Verzeichnisses zuzugreifen. Dekodiere und validiere Pfade vor Dateioperationen.
  • Verwende parametrisierte Abfragen. Verkette Benutzereingaben auch nach der URL-Dekodierung niemals direkt in SQL- oder NoSQL-Abfragen. Verwende parametrisierte Abfragen oder ein ORM.
  • Begrenze die URL-Länge. Extrem lange Query-Strings können einen Denial-of-Service verursachen. Konfiguriere deinen Webserver so, dass er URLs oberhalb einer angemessenen Länge ablehnt.
  • Kodiere auch die Ausgabe. Wenn du Query-Parameterwerte in HTML-Antworten zurückspiegelst, wende HTML-Entity-Kodierung an, um Cross-Site-Scripting-Angriffe (XSS) zu verhindern.

Verwandte Artikel

Testen Sie unsere kostenlosen Tools