Bewährte Methoden für RESTful-Web-API-Implementierung

In diesem Artikel werden bewährte Methoden zum Implementieren, Bereitstellen und Ausführen einer RESTful-Web-API beschrieben. Der Schwerpunkt liegt auf der Anfragenverarbeitung, Leistung, Zuverlässigkeit, Veröffentlichung und Überwachung. Anleitungen zur Ressourcenmodellierung und zum API-Design finden Sie unter Web API design.

Die Architekturleitlinien gelten für Implementierungssprachen und Frameworks. Die C#-Beispiele veranschaulichen ASP.NET Core Controller.

Verarbeiten von Anforderungen

Beachten Sie die folgenden Punkte, wenn Sie den Code zum Behandeln von Anforderungen implementieren.

Behalten Sie die HTTP-Methodensemantik bei und implementieren Sie Idempotenz.

Verwenden Sie GET, um Ressourcendaten zurückzugeben, und HEAD, um Antwortheader ohne Textkörper zurückzugeben. Verwenden Sie keine der beiden Methoden, um Ressourcen zu erstellen, zu aktualisieren oder zu löschen.

GET, HEAD, PUT und DELETE müssen idempotent sein, sodass das Wiederholen einer identischen Anfrage den gleichen beabsichtigten Effekt hat wie wenn sie einmal ausgeführt wird. Beispielsweise ändert DELETE den Ressourcenstatus, aber eine Wiederholung löscht keine zusätzlichen Ressourcen. Die erste DELETE-Anforderung kann 204 (Kein Inhalt) zurückgeben, während eine nachfolgende Anforderung 404 (Nicht gefunden) zurückgibt.

POST und PATCH sind nicht inhärent idempotent. Ein PATCH-Vorgang, der eine Eigenschaft auf einen Wert festlegt, kann idempotent sein, aber einer, der einen Zähler erhöht, ist nicht. Dokumentieren Sie, welche Zustandsveränderungsvorgänge Clients sicher wiederholen können. Wenn Sie Wiederholungsversuche für Vorgänge unterstützen, die nicht natürlich idempotent sind, implementieren und dokumentieren Sie, wie der Dienst doppelte Auswirkungen verhindert. Zur Semantik der Methoden siehe HTTP-Anfragemethoden.

Hinweis

Anleitungen zur Implementierung finden Sie unter Idempotent Consumer-Muster. Identifizieren Sie in der Praxis zunächst, ob eine Operation natürlich idempotent ist. Wenden Sie andernfalls künstliche idempotenz an, indem Sie verarbeitete Nachrichten-IDs nachverfolgen und Duplikate proaktiv oder reaktiv behandeln.

Validieren von Anforderungsdaten und Steuern des Feldzugriffs

Definieren Sie Anfrage- und Antwortmodelle, die nur die Felder im API-Vertrag offenlegen. Ordnen Sie diese Modelle den gespeicherten Daten zu, anstatt Request-Bodys direkt an Datenbankentitäten zu binden oder jede gespeicherte Eigenschaft zurückzugeben. Verhindern Sie, dass Aufrufer geschützte Eigenschaften durch Übermittlung zusätzlicher Felder ändern, und lassen Sie Eigenschaften weg, zu deren Lesung sie nicht berechtigt sind. Datenübertragungsobjekte (DATA Transfer Objects, DTOs) sind eine Möglichkeit, diese Grenze zu erzwingen. Weitere Informationen finden Sie unter Verhindern von Overposting in ASP.NET Core.

Überprüfen Sie die erforderlichen Felder, Typen, Bereiche und Geschäftsregeln, bevor Sie Änderungen speichern. Wenn Sie die Feldauswahl unterstützen, überprüfen Sie angeforderte Felder anhand einer Allowlist und der Berechtigungen des Aufrufers, bevor Sie die Antwort auf die angeforderten Felder beschränken. Wenden Sie dokumentierte Grenzwerte auch auf Filterung und Sortierung an. Informationen zu den entsprechenden Vertragsoptionen finden Sie unter Implementieren der Paginierung und Filterung.

Beschränken der Nebenwirkungen von POST-Aktionen, die Ressourcen erstellen

Wenn eine POST-Anforderung eine Ressource erstellt, beschränken Sie ihre Auswirkungen auf diese Ressource und direkt verwandte Ressourcen. Das Erstellen einer Bestellung kann z. B. auch den Bestand aktualisieren und Abrechnungsinformationen generieren. Sollte keine nicht zusammenhängenden Informationen ändern.

Vermeiden Sie die Implementierung von geschwätzigen POST-, PUT- und DELETE-Vorgängen

Vermeiden Sie das Entwerfen Ihrer API basierend auf Chatty-Vorgängen . Jede Anforderung weist ein Protokoll, ein Netzwerk und einen Rechenaufwand auf. Wenn Sie z. B. 100 kleinere Anfragen anstelle einer größeren Batchanforderung ausführen, entsteht zusätzlicher Aufwand im Client, im Netzwerk und auf dem Ressourcenserver. Bei Workloads, die Massenvorgänge benötigen, sollten Sie begrenzte Batchanforderungen anstelle vieler einzelner Anforderungen in Betracht ziehen.

  • Eine GET-Anforderung an eine Sammlung kann mehrere Ressourcen gleichzeitig abrufen.
  • Eine POST-Anforderung kann die Details für mehrere neue Ressourcen enthalten und sie alle zur gleichen Sammlung hinzufügen.
  • Eine PUT-Anforderung kann den gesamten Satz von Ressourcen in einer Sammlung ersetzen.
  • Eine DELETE-Anforderung kann eine gesamte Sammlung entfernen.

Definieren Sie maximale Batchgrößen, Nutzlastgrößen, Ausführungszeiten und Nebenläufigkeit. Geben Sie an, ob ein Batch atomisch ist oder teilweise erfolgreich ist, und geben Sie ein Ergebnis für jeden Vorgang zurück. Autorisieren und überprüfen Sie jeden Vorgang im Batch.

Wenn Sie OData verwenden, können Sie ASP.NET Core OData verwenden, um Batchanforderungen zu implementieren. Weitere Informationen finden Sie unter ASP.NET Core OData-Übersicht.

Befolgen der HTTP-Spezifikation beim Senden einer Antwort

Geben Sie den entsprechenden HTTP-Statuscode, Header und Textkörper zurück, damit Clients die Antwort interpretieren und verarbeiten können.

Beispielsweise sollte ein POST-Vorgang, der eine Ressource synchron erstellt, 201 (Erstellt) zurückgeben und die Ressource im Antwortheader Location identifizieren. Ein Vorgang, der Arbeit für die spätere Verarbeitung akzeptiert, kann 202 (Akzeptiert) zurückgeben, aber diese Antwort gibt nicht an, dass die Arbeit erfolgreich war. Fügen Sie keinen Antworttext mit 204 (Kein Inhalt) oder 304 (nicht geändert) hinzu. Weitere Informationen finden Sie unter HTTP-Anforderungsmethoden.

Unterstützung der Inhaltsaushandlung

Ein Antworttext kann Daten in verschiedenen Formaten enthalten, z. B. JSON oder XML. Clients können den Accept-Anfrageheader verwenden, um unterstützte Medientypen anzugeben. Beispielsweise kann ein Client, der ein Bild anfordert, angeben image/jpeg, image/gif, image/png. Geben Sie eine unterstützte Darstellung zurück und geben Sie ihren Medientyp im Antwortheader Content-Type an.

Wenn der Client keine Kopfzeile angibt Accept , verwenden Sie ein dokumentiertes Standardformat. ASP.NET Core-Controller verwenden standardmäßig JSON-Formatierer. Definieren Sie, was geschieht, wenn die API keine angeforderte Darstellung erzeugen kann. Konfigurieren Sie beispielsweise die API so, dass 406 (Nicht akzeptabel) zurückgegeben wird, anstatt stillschweigend ein nicht unterstütztes Format zurückzugeben. Weitere Informationen finden Sie unter Formatieren von Antwortdaten in ASP.NET Core Web-API.

Überprüfen Sie bei Anfragen mit einem Textkörper die Content-Type der Anfrage und akzeptieren Sie nur die Formate, die der Vorgang unterstützt. Gibt 415 (Nicht unterstützter Medientyp) für ein nicht unterstütztes Format zurück. Diese Prüfung ist getrennt von der Antwortverhandlung über Accept. Konfigurieren Sie in ASP.NET Core Eingabeformatierer, und verwenden Sie [Consumes], wenn Sie die Anforderungsformate eines Vorgangs einschränken müssen. Weitere Informationen finden Sie unter Erstellen von Web-APIs mit ASP.NET Core.

Ausgewählte API-Versionierungsstrategie implementieren

Wenden Sie die Versionierungsstrategie an, die Sie während des Entwurfs ausgewählt haben, konsistent in der Anwendung und im Gateway. Leiten Sie Anfragen an den Handler und das Antwortschema für die ausgewählte Version weiter. Definieren Sie das Verhalten für ausgelassene, falsch formatierte und nicht unterstützte Versionsbezeichner, anstatt stillschweigend zu ändern, welchen Kontrakt ein vorhandener Aufrufer empfängt.

Bewahren Sie die Request- und Response-Verträge der unterstützten Versionen auf. Wenn Sie einen Breaking Change einführen, stellen Sie eine neue Version bereit, und halten Sie die unterstützten früheren Versionen zur Verfügung. Behandeln Sie Anfragen von älteren Aufrufern, die neu hinzugefügte optionale Felder weglassen. Weitere Informationen finden Sie unter API-Versionsverwaltung und -kompatibilität.

Bewahren Sie generierte Ressourcenverknüpfungen und zwischengespeicherte Darstellungen konsistent mit der ausgewählten Version auf. Stellen Sie bei der headerbasierten Versionsverwaltung sicher, dass zwischengespeicherte Anfragen für unterschiedliche Versionen unterschieden werden, anstatt nur auf den URI zu vertrauen.

Auflösen und Autorisieren des Mandantenkontexts

Ermitteln Sie für eine mandantenfähige API den Mandanten für jede Anforderung, und überprüfen Sie, ob der authentifizierte Aufrufer auf diesen Mandanten zugreifen kann. Behandeln Sie Mandanten-IDs in Pfaden, Hostnamen und Headern nur als Routingeingaben. Weitere Informationen finden Sie unter Zuordnen von Anforderungen zu Mandanten in einer mehrmandantenfähigen Lösung.

Verwenden Sie den autorisierten Mandantenkontext konsistent beim Abfragen oder Aktualisieren von Daten und beim Übergeben von Arbeiten an Hintergrundprozessoren. Wenn Anwendungs- oder Gatewaycaches mandantenspezifische Daten speichern, schließen Sie den Mandantenbezeichner in den Cacheschlüssel ein. Informationen zu gatewayspezifischen Anleitungen finden Sie unter API-Verwaltungsfeatures, die Mehrinstanzenfähigkeit unterstützen.

Hypertext als Engine des Anwendungszustands (HATEOAS) verwendet Links, um Clients beim Auffinden und Navigieren von Ressourcen zu helfen. Beispielsweise kann eine Antwort, die Kundendetails enthält, Links zu den Bestellungen dieses Kunden enthalten. Beschreiben Sie die Vorgänge, die jede verknüpfte Ressource unterstützt, z. B. GET, POST, PUT und DELETE, und stellen Sie die entsprechenden URIs bereit. Weitere Informationen finden Sie unter API-Design.

Im folgenden Beispiel wird eine anwendungsdefinierte Linkdarstellung verwendet. Dokumentieren Sie ihre Konventionen, anstatt davon auszugehen, dass Clients benutzerdefinierte Verknüpfungsfelder interpretieren können. Eine GET-Anforderung für einen Kunden gibt Links zu den Bestellungen dieses Kunden zurück:

GET https://api.contoso.com/customers/2 HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"customerId": 2,"customerName": "Bert","links": [
    {"rel": "self",
     "href": "https://api.contoso.com/customers/2",
     "action": "GET",
     "types": ["text/xml","application/json"]},
    {"rel": "self",
     "href": "https://api.contoso.com/customers/2",
     "action": "PUT",
     "types": ["application/x-www-form-urlencoded"]},
    {"rel": "self",
     "href": "https://api.contoso.com/customers/2",
     "action": "DELETE",
     "types": []},
    {"rel": "orders",
     "href": "https://api.contoso.com/customers/2/orders",
     "action": "GET",
     "types": ["text/xml","application/json"]},
    {"rel": "orders",
     "href": "https://api.contoso.com/customers/2/orders",
     "action": "POST",
     "types": ["application/x-www-form-urlencoded"]}
]}

Der folgende Customer Datensatz stellt die Kundendaten dar. Die Eigenschaft Links enthält die HATEOAS-Links.

public sealed record Customer(
    int CustomerId,
    string CustomerName,
    IReadOnlyList<Link> Links);

public sealed record Link(
    string Rel,
    string Href,
    string Action,
    IReadOnlyList<string> Types);

Der GET-Vorgang ruft die Kundendaten aus dem Speicher ab, erstellt einen Customer Datensatz mit seinen Verknüpfungen und gibt eine JSON-Antwort zurück. Jeder Link enthält die folgenden Felder:

  • Die Beziehung (Rel) zwischen der zurückgegebenen Ressource und der verknüpften Ressource. In diesem Beispiel self bezieht sich auf den Kunden und orders bezieht sich auf die Bestellauflistung des Kunden.
  • Der Hyperlink (Href) für das Objekt, das durch den Hyperlink repräsentiert wird, in Form einer URI.
  • Der Typ der HTTP-Anforderung (Action), die an den URI gesendet werden kann.
  • Das Format der Daten (Types), die in der HTTP-Anforderung bereitgestellt werden sollen oder die je nach Art der Anforderung in der Antwort zurückgegeben werden können.

Mit den HATEOAS-Links in der HTTP-Beispielantwort wird angegeben, dass eine Clientanwendung die folgenden Vorgänge durchführen kann:

  • Eine HTTP-GET-Anforderung an https://api.contoso.com/customers/2, um die Kundendetails als XML oder JSON abzurufen.
  • Eine HTTP PUT-Anforderung an https://api.contoso.com/customers/2, um die Kundendetails zu ändern. Der Request-Body verwendet dieses Format: application/x-www-form-urlencoded.
  • Eine HTTP-DELETE-Anforderung an https://api.contoso.com/customers/2, um den Kundendatensatz zu löschen. Dieser Vorgang erfordert keinen Request-Body und gibt keinen Response-Body zurück.
  • Eine HTTP GET-Anforderung zum https://api.contoso.com/customers/2/orders Abrufen der Bestellungen des Kunden als XML oder JSON.
  • Eine HTTP-POST-Anforderung an https://api.contoso.com/customers/2/orders, um eine Bestellung für den Kunden zu erstellen. Der Request-Body verwendet dieses Format: application/x-www-form-urlencoded.

Behandeln von Ausnahmen

Wenn ein Vorgang eine Ausnahme auslöst, die nicht behandelt wird, beachten Sie die folgenden Anleitungen.

Erfassen von Ausnahmen und Zurückgeben einer aussagekräftigen Antwort an Clients

Behandeln Sie Ausnahmen konsistent, und geben Sie eine sinnvolle Fehlerantwort zurück, die sicher für Clients freigegeben werden kann. Geben Sie keine Ausnahmeobjekte, Stacktraces oder internen Implementierungsdetails in Produktionsantworten zurück. Gibt einen HTTP-Statuscode zurück, der den Fehler widerspiegelt, anstatt statuscode 500 für jede Situation zurückzugeben. Wenn z. B. eine Benutzeranforderung eine Datenbankaktualisierung verursacht, die gegen eine Einschränkung verstößt (z. B. den Versuch, einen Kunden zu löschen, der über ausstehende Bestellungen verfügt), geben Sie 409 (Konflikt) und eine sichere Erklärung zurück. Gibt 400 (ungültige Anforderung) für fehlerhafte Eingaben oder Fehler bei der Anforderungsvalidierung zurück, nicht für unerwartete Serverfehler. Definitionen zu HTTP-Statuscodes finden Sie unter Status Codes. Anleitungen zur Implementierung finden Sie unter "Behandeln von Fehlern in ASP.NET Core".

Der folgende Controller ordnet die erwarteten Domänenergebnisse HTTP-Antworten zu. Der Repositoryvorgang überprüft Autorisierung und ausstehende Aufträge im Rahmen des Löschvorgangs. Unerwartete Fehler werden an die zentrale Ausnahmebehandlung weitergegeben, anstatt in den einzelnen Aktionen automatisch abgefangen zu werden.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Authorize]
[Route("customers")]
public sealed class CustomersController(ICustomerRepository repository) : ControllerBase
{
    [HttpDelete("{id:int}")]
    public async Task<IActionResult> DeleteCustomer(int id, CancellationToken cancellationToken)
    {
        var outcome = await repository.DeleteAuthorizedAsync(id, User, cancellationToken);

        return outcome switch
        {
            DeleteOutcome.Deleted => NoContent(),
            DeleteOutcome.NotFound => NotFound(),
            DeleteOutcome.HasOutstandingOrders => Conflict(new ProblemDetails
            {
                Status = StatusCodes.Status409Conflict,
                Title = "The customer has outstanding orders."
            }),
            _ => throw new InvalidOperationException("Unknown deletion outcome.")
        };
    }
}

public enum DeleteOutcome
{
    Deleted,
    NotFound,
    HasOutstandingOrders
}

Important

Schließen Sie keine Informationen ein, die für einen Angreifer nützlich sein könnten, der versucht, nicht autorisierten Zugriff auf Ihre API zu erhalten.

Die Hostingebene kann Anfragen ablehnen, bevor sie die API erreichen. Authentifizierungsfehler können beispielsweise zu 401-Antworten (Nicht autorisiert) führen. Überprüfen Sie nach der Authentifizierung, ob der Aufrufer berechtigt ist, auf die angeforderte Ressource zuzugreifen. Gibt 403 (Verboten) zurück, wenn die Autorisierung fehlschlägt.

Einheitliches Behandeln von Ausnahmen und Protokollieren von Informationen zu Fehlern

Um Ausnahmen konsistent zu behandeln, sollten Sie eine globale Fehlerbehandlungsstrategie für die gesamte Web-API implementieren. Protokollieren Sie Diagnoseinformationen auf dem Server, schließen Sie jedoch geheime Schlüssel, Zugriffstoken und vertrauliche personenbezogene Daten aus. Schwärzen Sie sensible Werte, bevor Sie Protokolleinträge schreiben, und beschränken Sie den Zugriff auf Protokolle auf autorisierte Benutzer. Weitere Informationen finden Sie unter Architekturstrategien zur Überwachung und Bedrohungserkennung.

Verwenden Sie in ASP.NET Core Middleware zur Ausnahmebehandlung und Problem-Details-Antworten für einen konsistenten Fehlervertrag. Konfigurieren Sie Produktionsantworten, um Diagnosedetails auszulassen, und fügen Sie einen Korrelationsbezeichner ein, der Teams verwenden kann, um die entsprechenden Protokolle zu finden. Weitere Informationen finden Sie unter Fehlerbehandlung in ASP.NET Core.

Unterscheiden zwischen clientseitigen und serverseitigen Fehlern

Verwenden Sie HTTP 4xx-Statuscodes für Clientfehler und HTTP 5xx-Statuscodes für Serverfehler. Bewahren Sie diese Unterscheidung bei Fehlerantworten auf.

Optimierung des clientseitigen Datenzugriffs

Häufige Anfragen und große Antworten können das Netzwerk zu einem Engpass machen. Reduzieren Sie unnötige Übertragungen, wenn Sie Ressourcenabrufe und -updates implementieren.

Unterstützen der clientseitigen Zwischenspeicherung

Verwenden Sie den Cache-Control Antwortheader, um anzugeben, ob Clients und Zwischenserver eine Antwort speichern können und wie lange sie aktuell bleibt.

Das folgende Beispiel enthält eine HTTP GET-Anforderung und die dazugehörige Antwort mit einem Cache-Control-Header:

GET https://api.contoso.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
Content-Length: 59

{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}

In diesem Beispiel bleibt die Antwort 600 Sekunden lang gültig. Die private Direktive erlaubt die Speicherung in einem privaten Cache, z. B. einem Browsercache, verbietet jedoch die Speicherung in einem freigegebenen Cache. Verwenden Sie public nur für Antworten, die sicher für Anrufer freigegeben werden können. Verwenden Sie no-store für vertrauliche Antworten, die nicht gespeichert werden dürfen.

Legen Sie in einem ASP.NET Core-Controller Cacheheader fest, bevor Sie die Antwort zurückgeben:

Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
{
    Private = true,
    MaxAge = TimeSpan.FromMinutes(10)
};

Hinweis

Die no-cache Direktive erlaubt die Speicherung, erfordert jedoch eine erneute Überprüfung vor der Wiederverwendung. Verwenden Sie no-store, um die Speicherung zu verhindern.

Die API steuert die Cacherichtlinie und Validatoren in ihren Antworten. Clients und Zwischenserver verwenden diese Informationen, um ihre Caches zu verwalten. Legen Sie diese Header konsistent fest, damit Anrufer Antworten ohne unnötige Datenübertragungen wiederverwenden können.

Um max-age zu bestimmen, überlegen Sie, wie viele veraltete Daten die Workload tolerieren kann. Eine Ressource kann sich ändern, während eine zwischengespeicherte Antwort noch aktuell ist. Wenn die Gültigkeitsdauer abläuft, kann ein Cache die Antwort erneut validieren, anstatt sie zu verwerfen und die gesamte Repräsentation erneut herunterzuladen. Verwenden Sie keine lange Gültigkeitsdauer für Daten, die eine sofortige Sichtbarkeit von Änderungen erfordern.

Bereitstellen von ETags zum Optimieren der Abfrageverarbeitung

Ein Entity-Tag (ETag) ist ein undurchsichtiger Validator für eine ausgewählte Ressourcendarstellung. Clients können sie mit einer zwischengespeicherten Antwort beibehalten und sie in If-None-Match senden, um zu überprüfen, ob sich die Darstellung geändert hat. Eine übereinstimmende GET- oder HEAD-Anforderung gibt 304 (Nicht geändert) ohne Antworttext zurück.

Generieren Sie einen Validator, der in allen Anwendungsinstanzen konsistent bleibt und sich ändert, wenn sich die Darstellung ändert.

Der folgende Controller hasht die genauen JSON-Bytes, die er zurückgibt, und verwendet die konfigurierten JSON-Optionen der Anwendung wieder. FileContentResultwendet die Behandlung bedingter Antworten in ASP.NET Core ohne benutzerdefinierte Ergebniswrapper an. Das Repository gibt nur eine Bestellung zurück, zu deren Lesen der Aufrufer berechtigt ist. Konfigurieren Sie die Authentifizierung und Autorisierung in der Hostanwendung.

using System.Security.Cryptography;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;

[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrdersController(IOrderRepository repository,IOptions<JsonOptions> jsonOptions) : ControllerBase
{
    [HttpGet("{id:int}")]
    [HttpHead("{id:int}")]
    public async Task<IActionResult> GetOrder(int id, CancellationToken cancellationToken)
    {
        var order = await repository.FindAuthorizedAsync(id, User, cancellationToken);
        if (order is null)
        {
            return NotFound();
        }

        var payload = JsonSerializer.SerializeToUtf8Bytes(order, jsonOptions.Value.JsonSerializerOptions);
        var etag = new EntityTagHeaderValue($"\"{Convert.ToHexString(SHA256.HashData(payload))}\"");

        Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
        {
            Private = true,
            MaxAge = TimeSpan.FromMinutes(10)
        };

        return new FileContentResult(payload, "application/json")
        {
            EntityTag = etag
        };
    }
}

In diesem Beispiel wird die Darstellung gepuffert und die Bestellung auch für eine bedingte Anforderung gelesen. Verwenden Sie sie nur für begrenzte, nicht sensible Antworten. Bei großen Ressourcen sollten Sie ein gespeichertes Versionstoken verwenden, das sich ändert, wenn sich die ausgewählte Darstellung ändert, damit Sie eine Anforderung überprüfen können, ohne die vollständige Nutzlast zu generieren. Wenn Inhaltsverhandlung, Komprimierung oder Gatewaytransformationen die Darstellung ändern, stellen Sie sicher, dass Validatoren und Cachevariationen für diese Darstellung korrekt bleiben.

Eine Antwort enthält das ETag und die Cacherichtlinie. Die folgenden Beispiele zeigen die ersten 16 Hexadezimalzeichen (64 Bit) des SHA-256-Hashs des angezeigten JSON-Body, gefolgt von ... aus Platzgründen. Tatsächliche Header enthalten den vollständigen Hash ohne die Auslassungspunkte.

HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
ETag: "3097D1FD51082205..."
Content-Length: 59

{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}

Tipp

Verwenden Sie Cache-Control: no-store für Antworten, die vertrauliche Daten enthalten. Verwenden Sie private für andere benutzerspezifische Antworten, die zwischengespeichert werden können, um die Speicherung in gemeinsam genutzten Caches zu verhindern. Überlegungen zur Implementierung finden Sie unter Antwortzwischenspeicher-Middleware in ASP.NET Core.

Unterstützen Sie bedingte GET-Anforderungen, sodass Aufrufer zwischengespeicherte Antworten erneut validieren können, ohne eine unveränderte Darstellung herunterzuladen. Implementieren Sie das folgende Anfrage- und Antwortverhalten:

  1. Akzeptieren Sie bedingte GET-Anforderungen, die im If-None-Match-Header ein ETag bereitstellen, z. B.:

    GET https://api.contoso.com/orders/2 HTTP/1.1
    If-None-Match: "3097D1FD51082205..."
    
  2. Vergleichen Sie das aktuelle ETag für die angeforderte Ressource (Ressource 2 in diesem Beispiel) mit der If-None-Match-Bedingung.

    • Wenn die Bedingung übereinstimmt, geben Sie 304 (Nicht geändert) ohne Antworttext zurück.

    • Wenn die Bedingung nicht übereinstimmt, wird 200 (OK) mit der aktuellen Darstellung zurückgegeben.

    • Wenn die angeforderte Ressource nicht mehr vorhanden ist, geben Sie 404 (Nicht gefunden) zurück.

Hinweis

Ein ETag macht eine Antwort nicht cache-sicher. Wenden Sie Cachedirektiven konsistent an, auch bei bedingten Antworten und Fehlerantworten, und verwenden Sie no-store für vertrauliche Daten.

Verwenden Sie die Frameworkunterstützung für bedingte Anfragen, sofern möglich. Wenn Sie Vergleiche selbst implementieren, behandeln Sie alle bereitgestellten Entitätstags, Wildcardbedingungen und Regeln für schwache gegenüber starken Vergleichen, anstatt nur das erste Tag zu vergleichen. Schließen Sie die entsprechenden ETag- und Cacheheader in 304 (Nicht geändert)-Antworten ein, und führen Sie die Autorisierung vor dem Zurückgeben von Ressourcenmetadaten durch.

Tipp

Mit einem gespeicherten Validator können Sie überprüfen, ob eine Darstellung geändert wurde, ohne die vollständige Ressource abzurufen. Dieser Ansatz kann die Datenübertragung und -verarbeitung reduzieren, wenn die Ressource umfangreich oder deren Abruf kostspielig ist.

Verwenden von ETags zum Unterstützen der optimistischen Parallelität

Um verlorene Aktualisierungen zu verhindern, prüfen Sie If-Match-Vorbedingungen bei zustandsändernden Anfragen anhand des aktuellen ETag der Ressource. Auf diese Weise kann die API eine Änderung basierend auf einer Darstellung ablehnen, die ein anderer Vorgang bereits geändert hat. Implementieren Sie das folgende Verhalten:

  1. Akzeptieren Sie Updateanforderungen, die die erwartete Version im If-Match Header identifizieren. Die folgende PUT-Anfrage aktualisiert Bestellung 2. Es verwendet das ETag aus der früheren GET-Antwort, gekürzt auf die gleiche Weise. Die Kennzeichnung identifiziert die vorhandene Darstellung, nicht den neuen Request-Body:

    PUT https://api.contoso.com/orders/2 HTTP/1.1
    If-Match: "3097D1FD51082205..."
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 37
    
    productId=3&quantity=5&orderValue=250
    
  2. Vergleichen Sie das aktuelle ETag für die angeforderte Ressource (Bestellung 2 in diesem Beispiel) mit der If-Match Bedingung.

    • Wenn die Vorbedingung übereinstimmt, führen Sie die Aktualisierung atomisch aus, und geben Sie die dokumentierte Erfolgsantwort zurück, z. B. 204 (Kein Inhalt). Ein Location Header ist nicht erforderlich, nur weil eine vorhandene Ressource aktualisiert wurde. Ein ETag wird nur für eine erfolgreiche PUT-Antwort zurückgegeben, wenn es die HTTP-Validatoranforderungen für die gespeicherte Darstellung erfüllt.

    • Wenn die Voraussetzung nicht erfüllt ist, wird 412 (Vorbedingung fehlgeschlagen) zurückgegeben. In diesem Beispiel wird kein Antworttext zurückgegeben.

    • Wenn die zu aktualisierende Ressource nicht mehr vorhanden ist, geben Sie 404 (Nicht gefunden) zurück.

  3. Dokumentieren Sie die Erfolgs- und Konfliktantworten, damit Anrufer bestimmen können, ob ein Update erfolgreich war oder ob sie die aktuelle Darstellung abrufen müssen, bevor sie eine andere Änderung übermitteln.

Für Vorgänge, die verloren gegangene Updates verhindern müssen, müssen Sie eine Vorbedingung If-Match anfordern und 428 (Vorbedingung erforderlich) zurückgeben, wenn sie fehlt. Verwenden Sie einen strengen Vergleich für If-Match.

Wenn Sie eine Version im Anwendungsspeicher überprüfen und dann bedingungslos speichern, erzeugt dies eine Race-Condition. Erzwingen Sie den Versionsvergleich sowie den atomaren Schreibvorgang im Datenspeicher. Verwenden Sie z. B. ein Datenbankkoncurrencytoken, sodass das Update nur erfolgreich ist, wenn die gespeicherte Version weiterhin mit der Version übereinstimmt, mit der die Anforderung ausgewertet wird.

Konfigurieren Sie in Entity Framework (EF) Core ein Parallelitätstoken und behandeln Sie DbUpdateConcurrencyException, anstatt eine gleichzeitige Änderung zu überschreiben. Ersetzen Sie im Datenzugriffscode der API nicht automatisch die erwartete Version und wiederholen Sie ein widersprüchliches Datenbankupdate nicht, es sei denn, die Semantik des Vorgangs erlaubt dies. Weitere Informationen finden Sie unter Behandeln von Parallelitätskonflikten.

Verarbeitung großer Anfragen und Antworten

Große Anfrage- und Antworttexte verbrauchen API-Speicher, Bandbreite und Verbindungskapazität. Implementieren Sie Streaming- und Ressourcengrenzwerte, sodass große Übertragungen den Dienst nicht überlasten. Berücksichtigen Sie beim Umgang mit erheblichen Datenmengen die folgenden Punkte:

Optimieren von Anforderungen und Antworten, die große Objekte enthalten

Für große Objekte, z. B. Bilder oder andere Binärdaten, unterstützen Sie Streaminguploads und Downloads.

Verwenden Sie asynchrone Streaming-APIs, und lassen Sie den Server das Transfer-Framing für die ausgehandelte HTTP-Version auswählen. Fügen Sie Transfer-Encoding: chunked nicht manuell zu jedem Teil einer Antwort hinzu. Streaming ist nicht auf HTTP/1.1-Chunked-Encoding beschränkt. Vermeiden Sie das Puffern einer vollständigen unbegrenzten Anforderung oder Antwort im Anwendungsspeicher.

Legen Sie Grenzwerte für Request-Body, Uploadlimits, Timeouts und Abbruchrichtlinien auf den Anwendungs- und Hostingebenen fest. Lehnen Sie eine überdimensionale Anfrage mit 413 (Content Too Large) ab, bevor Sie die Antwort starten.

Die HTTP-Komprimierung kann die Übertragungsgröße reduzieren, allerdings auf Kosten zusätzlicher Verarbeitung auf Server und Client. Ein Client kann z. B. senden Accept-Encoding: gzip. Wenn der Server Gzip-komprimierten Inhalt zurückgibt, identifizieren Sie die Codierung mithilfe von Content-Encoding: gzip.

Konfigurieren Sie die Komprimierung über die Hostingplattform oder Middleware, und messen Sie ihre Auswirkungen auf CPU-Auslastung und Bandbreite sowohl auf Client- als auch auf Serverseite.

  • Vermeiden Sie es, bereits komprimierte Formate erneut zu komprimieren.
  • Bevor Die Komprimierung für dynamisch generierte HTTPS-Antworten aktiviert wird, bewerten Sie Komprimierungsrisiken, z. B. BREACH, und wenden Sie geeignete Gegenmaßnahmen an. Auch wenn Sie die HTTPS-Komprimierung in Ihrer Middleware deaktivieren, ist Ihr Hostingserver möglicherweise für die Anwendung der Komprimierung konfiguriert.
  • Stellen Sie sicher, dass Cachevariationen und ETags korrekt bleiben, wenn sich die Inhaltscodierung ändert.

Anleitungen zur Komprimierungsimplementierung und Sicherheitsaspekte finden Sie unter Antwortkomprimierung in ASP.NET Core.

Unterstützung teilweiser Downloads großer Ressourcen

Wenn die API partielle Downloads großer Ressourcen unterstützt, bewerben Sie diese Funktion mit Accept-Ranges. Behandeln Sie HEAD-Anforderungen, indem Sie die Metadaten der Ressource, einschließlich ihrer Gesamtgröße Content-Length, ohne Antworttext zurückgeben. Für GET-Anforderungen, die einen unterstützten Bytebereich angeben, geben Sie 206 (Partieller Inhalt), einen Content-Length für den zurückgegebenen Teil zurück und ein Content-Range Element, das diesen Teil der Ressource identifiziert. Mit diesem Antwortvertrag können Aufrufer Teile einer Ressource abrufen, ohne dass die API das gesamte Objekt zurückgeben muss.

HTTP HEAD-Anforderungen und Teilantworten werden im API-Design ausführlicher beschrieben.

Behandeln von 100-Continue für große Uploads

Bei einem großen HTTP/1.1-Upload kann ein Client Anforderungsheader mit Expect: 100-continue senden und warten, bevor der Text übertragen wird. Der Server kann eine Zwischenantwort von 100 (Continue) senden oder die Anforderung ablehnen, ohne den vollständigen Request-Body zu erhalten. Dieser Austausch ist Teil einer Anforderung und nicht eine vorläufige leere Anforderung, auf die eine zweite vollständige Anforderung folgt.

Konfigurieren und testen Sie, wie der Hostingstapel und das Gateway Anforderungen mit und ohne Expect: 100-continueverarbeiten. Überprüfen Sie das Verhalten der API, wenn sie einen Upload akzeptiert oder ablehnt, und messen Sie die Auswirkungen auf die Serverressourcennutzung und die Anforderungslatenz.

Unterstützung der Seitennummerierung für Anfragen, die möglicherweise eine große Anzahl von Objekten zurückgeben

Das Abrufen einer gesamten großen Sammlung kann die Serververarbeitung, den Netzwerkdatenverkehr und die Latenz erhöhen.

Überprüfen Sie Paginierungseingaben auf dem Server, und erzwingen Sie eine maximale Seitengröße. Der folgende Controller veranschaulicht die Anfragevalidierung. Standardmäßig werden 10 Ergebnisse zurückgegeben und Grenzwerte außerhalb von 1 bis 100 oder Offsets außerhalb von 0 bis 10.000 abgelehnt. Diese Grenzen sind illustrativ. Wählen Sie Grenzwerte basierend auf der Workload und den Auslastungstests aus. Bei Verwendung von [ApiController] erzeugen Überprüfungsfehler eine Antwort von 400. Weitere Informationen finden Sie unter Erstellen von Web-APIs mit ASP.NET Core.

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrderCollectionsController(IOrderRepository repository) : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<IReadOnlyList<Order>>> GetOrders(
        [FromQuery, Range(1, 100)] int limit = 10,
        [FromQuery, Range(0, 10000)] int offset = 0,
        CancellationToken cancellationToken = default)
    {
        var orders = await repository.ListAuthorizedAsync(limit, offset, User, cancellationToken);
        return Ok(orders);
    }
}

Ein Client kann mithilfe von https://api.contoso.com/orders?limit=30&offset=50 30 Aufträge anfordern, beginnend bei Offset 50.

Fügen Sie über die im vorherigen Beispiel gezeigte Anforderungsüberprüfung hinaus einen Link zur nächsten Seite oder ein Fortsetzungstoken in das Antwortschema ein. Geben Sie beispielsweise die Bestellungen zurück, mit einer auf nextLink gesetzten https://api.contoso.com/orders?limit=30&offset=80-Eigenschaft, wenn eine andere Seite verfügbar ist. Filter, Sortierreihenfolge und API-Version im Link beibehalten. Lassen Sie nextLink aus, oder legen Sie es auf null auf der letzten Seite fest. Ein Beispiel für einen Next-Link-Vertrag finden Sie unter Microsoft Graph Paging.

Wenden Sie Filterung und Paginierung im Datenspeicher an, nicht nach dem Laden der gesamten Sammlung. Verwenden Sie eine deterministische Sortierreihenfolge. Bewerten Sie bei großen oder häufig wechselnden Sammlungen cursorbasierte Paginierung, um teure Offsets und instabile Seitengrenzen zu vermeiden.

Tipp

Erzwingen sie dokumentierte Grenzen für die Abfragekomplexität, Filterausdrücke und Anforderungsgröße. Testen Sie die Grenzen jedes Gateways, jedes Proxys und jedes Servers im Anforderungspfad.

Aufrechterhaltung der Reaktionsfähigkeit, Skalierbarkeit und Verfügbarkeit

Definieren Sie Latenz-, Durchsatz- und Verfügbarkeitsziele für die kritischen Vorgänge der API. Entwerfen und testen Sie für erwarteten Datenverkehr, Lastspitzen und Abhängigkeitsausfälle. Scale-out und die zustandslose Handhabung unterstützen diese Ziele. Berücksichtigen Sie die folgenden Implementierungsanforderungen.

Bereitstellen von asynchroner Unterstützung für Anforderungen mit langer Ausführungsdauer

Für Aufgaben, die über die Dauer eines normalen HTTP-Requests hinausgehen: Validieren und autorisieren Sie die Anfrage, speichern Sie die Aufgabe dauerhaft und geben Sie den Statuscode 202 (Accepted) zurück. Verlassen Sie sich nicht darauf, dass ein nicht nachverfolgter, innerhalb des Prozesses ablaufender Task nach dem Senden einer Antwort noch abgeschlossen wird – Anwendungsneustarts, Skalierungsmaßnahmen (Scale-in) oder Bereitstellungsvorgänge können ihn unterbrechen. Verwenden Sie eine dauerhafte Warteschlange und einen Worker oder einen dauerhaften Workflow, wenn die Arbeit trotz dieser Ereignisse weiterhin ausgeführt werden muss. Die vollständige HTTP-Semantik und Implementierungsanleitung finden Sie unter "Asynchrones Request-Reply Muster".

Stellen Sie eine Möglichkeit bereit, damit Anrufer den Status und das Ergebnis des Vorgangs abrufen können. Die API kann Aufrufer auch benachrichtigen, wenn die Verarbeitung abgeschlossen ist.

Sie können eine Statusressource bereitstellen, die Clients abfragen:

  1. Der Kunde sendet die Anfrage. Überprüfen Sie die Eingaben und Berechtigungen, bevor Sie Arbeit akzeptieren.
  2. Speichern Sie einen Vorgangsbezeichner und -status im dauerhaften Speicher, z. B. Azure Table Storage, und stellen Sie Arbeit für einen separaten Prozessor in die Warteschlange, z. B. mithilfe von Azure Service Bus. Koordinieren Sie Persistenz und Queueing, sodass ein Fehler zwischen diesen beiden Aktionen nicht zum Verlust der akzeptierten Arbeit führt.
  3. Gibt 202 mit einem Location Header zurück, der den Statusendpunkt identifiziert, und einem Retry-After Header, der die Abrufhäufigkeit steuert. Akzeptieren Sie die Anfrage nur, nachdem die Arbeit dauerhaft aufgezeichnet wurde.
  4. Ein Worker verarbeitet den Vorgang und aktualisiert ihren persistenten Zustand. Machen Sie die Verarbeitung idempotent, da ein Worker dieselbe Arbeit mehr als einmal erhalten kann. Wenden Sie begrenzte Wiederholungsversuche auf vorübergehende Fehler an.
  5. Der Client fragt den Statusendpunkt ab. Autorisierung auf Ressourcenebene sowohl für die Status- als auch die Ergebnisendpunkte erzwingen. Ein nicht erratbarer Bezeichner ist keine Autorisierung.
  6. Gibt eine dokumentierte Statusdarstellung zurück, während die Arbeit ausgeführt wird. Geben Sie nach Abschluss das Ergebnis oder eine 303-Umleitung (See Other) zu einer Ergebnisressource an. Melden Sie Fehler über einen konsistenten, sicheren Fehlerkontrakt.
  7. Definieren sie Aufbewahrung und Bereinigung für Vorgangsdatensätze und -ergebnisse. Dokumentieren Sie den Ablauf von Vorgängen, mehrfache Einreichungen sowie sämtliche unterstützten Stornierungsmechanismen.

Für verbundene Clients sollten Sie ASP.NET Core SignalR für Benachrichtigungen über den Abschluss verwenden. Halten Sie die dauerhafte Statusressource zur Verfügung, damit Clients nach einer Unterbrechung der Verbindung oder einer verpassten Benachrichtigung wiederhergestellt werden können. Weitere Informationen finden Sie unter Übersicht über ASP.NET Core SignalR.

Sicherstellen, dass jede Anforderung zustandslos ist

Es sollte nicht erforderlich sein, dass eine spätere Anforderung dieselbe Anwendungsinstanz wie eine frühere Anforderung erreicht. Behalten Sie Workflow- und Ressourcenstatus in geeigneten freigegebenen Speichern, nicht nur im Prozessspeicher. Anfragen können vom dauerhaften Ressourcenstatus abhängen, ohne eine Bindung an eine Serverinstanz zu erzeugen. Zustandslose Anforderungsverarbeitung unterstützt die horizontale Skalierung.

Verstehen Sie Ihre nachgelagerten Abhängigkeiten

Legen Sie für jeden nachgeschalteten Aufruf ein Timeout fest. Behalten Sie die Gesamtzeit für Aufrufe, Wiederholungen und Verzögerungen innerhalb des Zeitlimits der API-Anforderung bei, und geben Sie die Abbruchanforderung an nachgelagerte Vorgänge weiter.

Wiederholen Sie nur bei vorübergehenden Fehlern und Vorgänge, die sicher wiederholt werden können. Verwenden Sie begrenzungsgebundene Wiederholungen mit Backoff und Jitter. Beschränken Sie aggregierte Wiederholungen pro Abhängigkeit sowie Versuche pro Anfrage. Weitere Informationen finden Sie unter Behandeln vorübergehender Fehler.

Verwenden Sie einen Circuit Breaker, wenn wiederholte Abhängigkeitsfehler die API-Kapazität ausschöpfen können.

Nachverfolgen von Clients und Implementieren der Drosselung, um die Gefahr von DoS-Angriffen zu verringern

Legen Sie Grenzwerte für Anforderungsrate, Parallelität, Payload und Ausführungszeit fest. Begrenzungen nach Möglichkeit anhand des authentifizierten Aufrufers oder Mandanten unterteilen. Gibt 429 (Zu viele Anforderungen) zurück, wenn ein Aufrufer eine konfigurierte Rate überschreitet, und 503 (Dienst nicht verfügbar) bei vorübergehender Nichtverfügbarkeit des Dienstes. Fügen Sie Retry-After ggf. ein. Wenn die API Aufrufe an nachgeschaltete Abhängigkeiten wiederholt, begrenzen Sie diese Wiederholungsversuche, damit sie keine Überlastung verstärken.

Gateway- und Anwendungsgrenzen dienen verschiedenen Zwecken. Gateway-Grenzwerte können gemeinsam genutzte Kapazität schützen. Anwendungsgrenzen können Betriebskosten und nachgelagerte Kapazitäten widerspiegeln. Keines von beiden ersetzt den DDoS-Schutz auf Netzwerkebene oder eine Webanwendungsfirewall. Weitere Informationen finden Sie unter Drosselungsmuster.

Sorgfältiges Verwalten von dauerhaften HTTP-Verbindungen

Konfigurieren Sie für eingehende Verbindungen Server- und Gateway-Keep-Alive-Timeouts, Anforderungstimeouts und gleichzeitige Verbindungsgrenzwerte für die Workload und den Netzwerkpfad. Erzwingen Sie nicht routinemäßig, dass Verbindungen nach jeder Antwort geschlossen werden. Informationen zu ASP.NET Core Servereinstellungen finden Sie unter Konfigurieren von Optionen für den Kestrel-Webserver.

Wenn die API selbst nachgeschaltete HTTP-Dienste aufruft, sollten Sie diese ausgehenden Verbindungen wiederverwenden. Verwenden Sie in einer .NET-API-Implementierung langlebige HttpClient-Instanzen mit einem geeigneten PooledConnectionLifetime, oder verwenden Sie Clients, die von IHttpClientFactory erstellt wurden. Verwerfen Sie ausgehende Antwortnachrichten und Datenströme, wenn sie nicht mehr benötigt werden. Diese Einstellungen gelten für die nachgeschalteten Aufrufe der API, nicht für eingehende Clientverbindungen. Ausführliche Informationen und Hinweise zur Cookiebehandlung finden Sie in den Richtlinien für die Verwendung von HttpClient.

Veröffentlichung und Verwaltung einer Web-API

Stellen Sie die API in einer Hostingumgebung bereit, die den Betriebsanforderungen der API entspricht. Erwägen Sie die folgenden Strategien:

  • Verwenden Sie HTTPS. Authentifizieren Sie Anfragen an geschützte Endpunkte, und erzwingen Sie die Autorisierung für jede Ressource und jeden Vorgang.
  • Skalieren Sie die Hostingumgebung so, dass die Reaktionszeitvorgaben erfüllt werden, wenn sich die Nachfrage ändert.
  • Anfragen messen, wenn das Abrechnungsmodell der API dies erfordert.
  • Datenverkehr regulieren und Clientkontingente bei Bedarf erzwingen.
  • Protokollieren Sie die Überwachungsereignisse, die Compliance und Reaktion auf Sicherheitsvorfälle erfordern, protokollieren Sie jedoch keine Anmeldeinformationen, Token oder vertrauliche Anforderungs- und Antworttexte.
  • Überwachen Sie die Hostintegrität, und definieren Sie Wiederherstellungsaktionen, z. B. den Neustart eines fehlerhaften Hosts.

Erwägen Sie die Verwendung einer separaten Facade, die gemeinsame Verwaltungsaspekte behandelt und validierte Anfragen an die API weiterleitet. Eine Fassade kann die folgenden Funktionen bieten:

  • Sie dient als Integrationspunkt für mehrere Web-APIs.
  • Sie ermöglicht das Transformieren von Nachrichten und das Übersetzen von Kommunikationsprotokollen für Clients, die mit unterschiedlicher Technologie erstellt wurden.
  • Sie ermöglicht das Zwischenspeichern von Anforderungen und Antworten, um die Auslastung des Servers zu reduzieren, auf dem die Web-API gehostet wird.

Halten Sie API-Verträge und Gatewaykonfiguration unter Versionskontrolle, überprüfen Sie Änderungen in Bereitstellungspipelinen, und definieren Sie Rollbackprozeduren. Richten Sie Hosting, Identität, Netzwerk und Governance am Landing-Zone-Ansatz der Organisation aus. Weitere Informationen finden Sie unter Was ist eine Azure-Landezone?.

Testen einer Web-API

Verwenden Sie Unit-Tests, um die Logik der API zu validieren, und Integrationstests, um ihr HTTP-Verhalten zu überprüfen.

Fügen Sie die folgenden Prüfungen ein:

  • Testen Sie alle Routen, um zu überprüfen, ob dabei die richtigen Vorgänge aufgerufen werden. Achten Sie besonders darauf, dass der HTTP-Statuscode 405 (Methode nicht zulässig) unerwartet zurückgegeben werden kann. Dieser Statuscode kann auf einen Konflikt zwischen einer Route und den HTTP-Methoden (GET, POST, PUT, DELETE) hinweisen, die für diese Route verarbeitet werden können.

    Senden Sie Anfragen, die Methoden verwenden, die von der jeweiligen Route nicht unterstützt werden, und überprüfen Sie die dokumentierte 405-Antwort (Methode nicht zulässig) und den Allow-Header.

  • Vergewissern Sie sich, dass alle Routen richtig geschützt sind und geeignete Authentifizierungs- und Autorisierungsüberprüfungen aufweisen.

    Hinweis

    Einige Aspekte der Sicherheit, z. B. die Benutzerauthentifizierung, sind wahrscheinlich die Verantwortung der Hostumgebung anstelle der Web-API, aber Sie müssen weiterhin Sicherheitstests als Teil des Bereitstellungsprozesses einbeziehen.

  • Testen Sie die Ausnahmebehandlung, die von den einzelnen Vorgängen durchgeführt wird, und stellen Sie sicher, dass eine passende und aussagekräftige HTTP-Antwort zurück an die Clientanwendung übergeben wird.

  • Achten Sie darauf, dass Anforderungs- und Antwortnachrichten richtig formatiert sind. Zum Beispiel überprüfen Sie bei einer POST-Anforderung, die eine Ressource erstellt, die Deserialisierung, das Parsen, die Ressourcenerstellung und den Location-Header der Antwort.

  • Testen Sie unterstützte und nicht unterstützte Request-Medientypen getrennt von der Antwortinhaltsverhandlung. Überprüfen Sie 415-Antworten („Unsupported Media Type“) bei nicht unterstützten Anfrageformaten sowie die dokumentierten Validierungsfehler bei fehlerhaft strukturierten Anfragetexten (Bodies).

  • Testen Sie jede unterstützte API-Version, einschließlich Routing, Anforderungsüberprüfung und Antwortschema. Testen Sie fehlende, falsch formatierte und nicht unterstützte Versionsbezeichner, und stellen Sie sicher, dass zwischengespeicherte Antworten keine Versionsgrenzen überschreiten.

  • Überprüfen Sie alle Links und URIs in Antwortnachrichten. Beispielsweise sollte eine HTTP POST-Nachricht den URI der neu erstellten Ressource zurückgeben. Alle HATEOAS-Links müssen gültig sein.

  • Stellen Sie sicher, dass jeder Vorgang für unterschiedliche Eingabekombinationen die richtigen Statuscodes zurückgibt. Beispiel:

    • Wenn eine Abfrage erfolgreich ist, sollte der Statuscode 200 (OK) zurückgegeben werden.
    • Wenn eine Ressource nicht gefunden wird, sollte der Vorgang DEN HTTP-Statuscode 404 (Nicht gefunden) zurückgeben.
    • Wenn der Client eine Anforderung sendet, mit der eine Ressource erfolgreich gelöscht wird, sollte der Statuscode 204 (No Content) lauten.
    • Wenn der Client eine Anforderung sendet, mit der eine neue Ressource erstellt wird, sollte der Statuscode 201 (Created) lauten.

    Untersuchen Sie unerwartete 5xx Antworten von der Anwendung oder Hostebene.

  • Testen Sie die unterschiedlichen Anforderungsheaderkombinationen, die von einer Clientanwendung angegeben werden können, und stellen Sie sicher, dass die Web-API in Antwortnachrichten die erwarteten Informationen zurückgibt.

  • Testen Sie Abfragezeichenfolgen. Wenn ein Vorgang optionale Parameter (z. B. Paginierungsanforderungen) annehmen kann, testen Sie die verschiedenen Kombinationen und die Reihenfolge der Parameter.

  • Vergewissern Sie sich, dass asynchrone Vorgänge erfolgreich abgeschlossen werden. Stellen Sie bei Streamingantworten sicher, dass die API die gesamte Nutzlast nicht puffert und Clienttrennungen und Abbrüche ordnungsgemäß verarbeitet. Wenn die API Statusressourcen für lange ausgeführte Vorgänge bereitstellt, überprüfen Sie, ob sie den Vorgangsfortschritt und die Ergebnisse korrekt melden.

Testen Sie die Fehler- und Grenzfälle, die sich auf die Korrektheit auswirken:

  • Überprüfen Sie minimale, maximale, negative, falsch formatierte und übermäßige Paginierungs- und Batcheingaben.
  • Folgen Sie den Paginierungslinks bis zur letzten Seite. Stellen Sie sicher, dass Links Abfrageoptionen beibehalten und das dokumentierte Abschlusssignal zurückgegeben wird.
  • Stellen Sie sicher, dass zusätzliche Eingabefelder geschützte Eigenschaften nicht ändern können und dass die Feldauswahl keinen unbefugten Zugriff auf Daten ermöglichen kann.
  • Testen Sie übereinstimmende, nicht übereinstimmende, schwache, mehrfache und Wildcard-ETags, und stellen Sie sicher, dass 304 Antworten keinen Text enthalten.
  • Üben Sie gleichzeitige Aktualisierungen aus, und stellen Sie sicher, dass der Datenspeicher veraltete Schreibvorgänge atomisch ablehnt.
  • Stellen Sie sicher, dass Anrufer die Ressourcen, Statusdatensätze oder zwischengespeicherten Antworten eines anderen Anrufers nicht lesen können.
  • Testen Sie bei mandantenfähigen APIs gefälschte oder nicht übereinstimmende Mandanten-IDs. Wenn die Zwischenspeicherung aktiviert ist, prüfen Sie Anfragen für denselben Ressourcen-URI von verschiedenen Mandanten.
  • Simulieren Sie Timeouts, Clientabbruch, Abhängigkeitsfehler, Neustarts von Workern und doppelte Übermittlung von Hintergrundarbeiten.
  • Überprüfen Sie Timeouts und Retry-Budgets für nachgelagerte Dienste, Abbruchmechanismen sowie die Wiederherstellung nach dem Auslösen eines Circuit-Breakers.
  • Überprüfen Sie 429 (Zu viele Anforderungen)- und 503 (Dienst nicht verfügbar)-Antworten, das Wiederholungsverhalten und die Kosten für das Ablehnen überlasteter Anforderungen.

Führen Sie Lasttests mit produktionsähnlicher Infrastruktur und realistischen Nutzungsmustern aus. Definieren Sie Bestehens- und Nichtbestehenskriterien für Durchsatz, Latenzquantile, Fehlerraten und Ressourcensättigung. Verwenden Sie Azure Load Testing und integrieren Sie Regressionsprüfungen in die Bereitstellungspipeline.

API-Verwaltung verwenden

Erwägen Sie die Verwendung von Azure API Management, wenn Sie ein verwaltetes Gateway mit Richtlinienerzwingung benötigen. Es werden Kosten, ein weiterer Netzwerksprung und eine Abhängigkeit im Request-Pfad hinzugefügt. Wählen Sie eine Dienstebene und Topologie basierend auf Kapazität, Netzwerk, Verfügbarkeit und regionalen Anforderungen aus; Die Features unterscheiden sich je nach Ebene. Die Entwicklerebene ist nicht für Produktionsworkloads vorgesehen. Folgen Sie dem Well-Architected Dienstleitfaden für die API Management.

Sie können eine Web-API veröffentlichen und verwalten, indem Sie die folgenden Schritte ausführen:

  1. Stellen Sie die Web-API auf einer Hostingplattform wie Azure App Service, Azure Container Apps, Azure Kubernetes Service (AKS) oder Azure Virtual Machines bereit.

  2. Konfigurieren Sie die API-Verwaltung, um Anforderungen von der Gateway-URL an die Back-End-API weiterzuleiten. Eine API-Verwaltungsinstanz kann Anfragen an mehrere APIs weiterleiten. Mehrere Instanzen können auch dieselbe Back-End-API verfügbar machen, wenn Anwendungen unterschiedliche Zugriffsgrenzen benötigen.

    Hinweis

    HATEOAS-Links in Antworten sollten auf die API Management-Gateway-URL verweisen, nicht auf die Back-End-Server-URL.

  3. Importieren Sie eine versionsgesteuerte OpenAPI-Definition, und überprüfen Sie, ob die importierten Vorgänge, Parameter, Sicherheitsanforderungen und Antwortschemas der Implementierung entsprechen. Überprüfen Sie unterstützte OpenAPI-Versionen und Importbeschränkungen. Weitere Informationen finden Sie unter Eine OpenAPI-Spezifikation importieren.

  4. Konfigurieren Sie die Authentifizierung und Autorisierung sowohl für die Client-zu-Gateway- als auch für die Gateway-zu-Back-End-Kommunikation. Überprüfen Sie OAuth 2.0-Zugriffstoken, und erzwingen Sie die für Clientanforderungen erforderlichen Berechtigungen. Bevorzugen Sie für Back-Ends, die Microsoft Entra ID-Authentifizierung unterstützen, eine verwaltete Identität in API Management, die nur über die benötigten Berechtigungen verfügt. Die Zertifikatauthentifizierung ist eine weitere Option. Vermeiden Sie die Basic-Authentifizierung, wenn sicherere Optionen verfügbar sind. Weitere Informationen finden Sie unter Authentifizierung und Autorisierung für APIs in Azure API Management.

    Hinweis

    Wenn Sie API-Verwaltungsabonnementschlüssel benötigen, verwenden Sie sie nicht als Ersatz für die Authentifizierung und autorisierung auf Ressourcenebene.

  5. Konfigurieren Sie Richtlinien für Authentifizierung, ursprungsübergreifenden Zugriff, Nachrichtentransformationen, IP-Filterung, Ratelimits und Kontingente nach Bedarf. Konfigurieren Sie das Zwischenspeichern von Antworten nur für Daten, die sicher zwischengespeichert werden können. Wenden Sie Richtlinien auf den geeigneten Geltungsbereich an, und überprüfen Sie ihr effektives Verhalten für jeden Vorgang.

Weitere Informationen finden Sie in der API-Verwaltungsdokumentation.

Important

Ein Gateway macht das Back-End nicht privat oder ersetzt keine Autorisierung auf Ressourcenebene. Entwerfen Sie Back-End-Zugriffssteuerungen, Fehlerbehandlung, Kapazität und Observierbarkeit für die gesamte Workload, einschließlich des Gateways. Bewerten Sie die Zonen- und regionale Redundanz gegenüber den Funktionen des ausgewählten Tiers. Schließen Sie Gatewaygebühren, Telemetrieerfassung und Aufbewahrung sowie die Datenübertragung in das Kostenmodell ein.

Unterstützung von clientseitigen Entwicklern

Stellen Sie API-Consumern Dokumentation für Authentifizierung, Vorgänge, Parameter, Datentypen und Antwortcodes zur Verfügung.

Dokumentieren der REST-Vorgänge für eine Web-API

Veröffentlichen Sie eine OpenAPI-Definition, die die Vorgänge, Parameter, Anforderungs- und Antwortschemas und Sicherheitsanforderungen der API beschreibt. Behalten Sie sie bei der Implementierung unter der Versionskontrolle bei, und stellen Sie sicher, dass sie dem tatsächlichen Verhalten der API entspricht.

Ergänzen Sie die API-Referenz mit Anleitungen, die Nutzer benötigen, um die API ordnungsgemäß zu verwenden:

  • Authentifizierungsanforderungen und Berechtigungen für jeden Vorgang.
  • Repräsentative Anfragen, erfolgreiche Antworten und Fehlerantworten.
  • Eingabeüberprüfungsregeln, Nutzlastbeschränkungen, Paginierungs- und Ratelimits.
  • Timeoutverhalten, Wiederholungssicherheit und alle Anforderungen an die Idempotenz.
  • Status- und Ergebnisabruf für lang andauernde Vorgänge.
  • Versionsverwaltung und Kompatibilitätserwartungen.

Halten Sie die Dokumentation und Beispiele auf dem neuesten Stand, wenn sich der API-Vertrag ändert.

Implementieren eines Client-SDK

Erwägen Sie die Bereitstellung eines SDK für API-Consumer. Das SDK kann typierte Methoden verfügbar machen, die Anfragen erstellen, Antworten parsen und die dokumentierten API-Fehler zurückgeben.

Erwägen Sie, typisierte Clients aus der OpenAPI-Definition der API zu generieren, aber validieren Sie das generierte Verhalten gegen den Dienst. Dokumentauthentifizierung, Timeouts, Abbruch, Paginierung, Fehlerantworten und welche Vorgänge sicher zu wiederholen sind. Halten Sie die Client- und API-Kompatibilitätsrichtlinie aufeinander abgestimmt. Generierter Code entfernt nicht die Notwendigkeit von Integrationstests.

Überwachen einer Web-API

Überwachen Sie die API, ihre Abhängigkeiten und jedes Gateway zusammen. Definieren Sie Service-Level-Ziele und Warnungen basierend auf den Auswirkungen auf den Kunden, anstatt nur auf die Hostintegrität zu vertrauen.

Direktes Überwachen einer Web-API

Verwenden Sie die OpenTelemetry-Instrumentierung, um Ablaufverfolgungen, Metriken und Protokolle zu sammeln und die Signale in Application Insights oder ein anderes unterstütztes Back-End zu exportieren. Befolgen Sie für .NET, Node.js und Python Instrumentierung die Microsoft OpenTelemetry Distro-Anleitung. Java verwendet die Azure Monitor OpenTelemetry Distro. Befolgen Sie die sprachspezifischen OpenTelemetry-Aktivierungsanleitungen.

Signale zur Überwachung, die das API-Verhalten beschreiben:

  • Anfragevolumen, Fehlerrate und Latenzperzentile nach Vorgang
  • Abhängigkeitslatenz, Fehler und Timeouts
  • Zurückweisungen aufgrund von Ratenbegrenzungen, gleichzeitige Arbeit und Ressourcensättigung
  • Alter der Hintergrundoperationswarteschlange, Abschlusszeit, Fehler und Wiederholungen
  • Cache-Effektivität, wenn zwischenspeichern Teil des Entwurfs ist

Die Telemetrie, die ein Überwachungstool sammelt, variiert je nach Sprache, Bibliotheken und Konfiguration automatisch. Fügen Sie die Instrumentierung für Domänenvorgänge und Hintergrundaufgaben hinzu. Gehen Sie nicht davon aus, dass Browsersitzungen, Benutzerrollen oder alle Anforderungsdetails automatisch verfügbar sind. Verteilt den Nachverfolgungskontext über das Gateway, die Anwendung und die Worker. Konfigurieren Sie Sampling und Aufbewahrung, um Diagnoseanforderungen, Datenempfindlichkeit und Telemetriekosten auszugleichen.

Verwenden Sie application Insights Standard-Verfügbarkeitstests für wiederkehrende externe Prüfungen, falls zutreffend. Überprüfen Sie einen aussagekräftigen Zustands- oder Betriebsendpunkt, ohne vertrauliche Daten verfügbar zu machen, umsetzbare Warnungen zu definieren und ein Antwort-Runbook zu verwalten.

Überwachen einer Web-API mithilfe von API Management

Verwenden Sie die Azure Monitor Metriken, Protokolle, Analysen und Diagnosen, die von der API-Verwaltung unterstützt werden, um Gatewayfehler von Back-End-Fehlern zu unterscheiden. Korrelieren Sie Gateway- und Anwendungstelemetrie, und überwachen Sie Richtlinienfehler, Kapazität, Anforderungslatenz und Drosselung. Die verfügbaren Signale hängen von der Konfiguration des Tarifs und des Gateways ab.

Befolgen Sie die Empfehlungen für Observability und Kapazität im Well-Architected Dienstleitfaden für die API-Verwaltung.

Nächste Schritte