API-Entwicklung
Laravel-API-Entwicklung
APIs, gegen die andere Teams bauen können - ein Vertrag, der erzeugt statt beschrieben wird, Authentifizierung mit einem Eigentümer, und Seitenaufteilung, die das Wachstum der Daten übersteht.
Eine API ist ein Versprechen an jemanden, der nicht im Raum ist. Das ist der ganze Unterschied zwischen ihr und dem Rest einer Anwendung: Ihre eigenen Bildschirme können sich gemeinsam mit dem Code dahinter ändern, ein Konsument kann das nicht.
Die meisten Laravel-APIs, die wir reparieren sollen, wurden gebaut, als wäre das nicht wahr.
Der Vertrag wird erzeugt, nicht beschrieben
Eine von Hand in ein Wiki geschriebene Spezifikation ist binnen zweier Sprints veraltet, und der Erste, der das entdeckt, ist ein Konsument, der dagegen gebaut hat.
Also kommt der Vertrag aus dem Code: typisierte Resources, Request-Validierung, aus der die Spezifikation abgeleitet wird, und ein erzeugtes OpenAPI-Dokument, das als Teil des Builds veröffentlicht wird. Eine Änderung an einer Antwortform ändert das Dokument im selben Pull Request. Es kann nur falsch sein, wenn der Code falsch ist.
Resources sind explizit, statt ein Modell an toJson() zu reichen. Ein Modell
direkt zurückzugeben heißt, dass eine aus internen Gründen hinzugefügte Spalte
an dem Tag Teil des öffentlichen Vertrags wird, an dem sie hinzukommt – und sie
später zu entfernen ist eine brechende Änderung, die Sie nie machen wollten.
Versionierung, entschieden bevor Sie sie brauchen
Version eins ist umsonst und Version zwei nicht, also ist die Entscheidung, die früh zu treffen ist: wo die Version lebt und was als brechend gilt.
Ein Feld hinzuzufügen bricht nicht. Eines zu entfernen, umzubenennen, einen Typ zu ändern oder die Validierung zu verschärfen schon. Die Form der Seitenaufteilung, die Form der Fehler und das Datumsformat gehören zum Vertrag, auch wenn niemand sie als solche aufschreibt – und jedes davon hat nach unserer Erfahrung mindestens einmal einen Konsumenten zerbrochen.
Was wir einrichten, ist eine Regel: additive Änderungen gehen laufend raus, brechende bekommen eine neue Version, beide Versionen laufen für ein vereinbartes Fenster parallel, und Konsumenten werden informiert statt entdeckt.
Authentifizierung mit einem Eigentümer
Sanctum für eigene Clients, Passport wo OAuth2 wirklich nötig ist, und in beiden Fällen eine Stelle, die entscheidet, was ein Token darf.
Der Fehler, den wir finden, ist Doppelung: eine Berechtigung in einer Policy für die Web-Routen geprüft und in einer Middleware für die API-Routen erneut umgesetzt, bis beide auseinanderdriften und eine davon falsch ist. Autorisierung gehört in Policies, die beide Eingänge aufrufen, und die API-Tests sichern die negativen Fälle zu – nicht dass die richtige Person den Datensatz lesen kann, sondern dass die falsche es nicht kann.
Ratenbegrenzung pro Konsument statt pro IP, denn pro IP bestraft ein Büro und verfehlt ein Skript. Fähigkeiten auf das begrenzt, wofür das Token da ist, damit ein geleaktes Mobile-Token kein Admin-Token ist.
Die Teile, die unter echten Daten brechen
Seitenaufteilung. Offset-Paginierung ist in Ordnung bis Seite vierhundert – ab da liest und verwirft die Datenbank vierhundert Seiten, um Ihnen eine zu geben. Cursor-Paginierung für alles, was wächst, entschieden beim Entwurf, denn sie später zu ändern ist eine brechende Änderung.
Filtern und Sortieren. Jeder Filter, den ein Konsument übergeben darf, ist ein Abfrageplan, den Sie bedienen können müssen. Eine Positivliste, mit einem Index hinter jedem Eintrag – sonst haben Sie einen Endpunkt veröffentlicht, den jeder mit einem Token beliebig langsam machen kann.
Verschachtelte Daten. Einem Konsumenten zu erlauben, verschachtelte Relationen anzufordern, ist eine gute Funktion und ein N+1-Generator. Vorab laden, gesteuert von den angeforderten Einbindungen, mit einer Tiefenbegrenzung – sonst wird die Bequemlichkeit zum Ausfall.
Fehler. Eine Form, dokumentiert, mit einem maschinenlesbaren Code, der sich nicht ändert, wenn die menschenlesbare Meldung es tut. Ein Konsument, der Ihre Fehlertexte parst, ist ein Konsument, den Sie zerbrechen, indem Sie Ihre Texte verbessern.
Wie ein Projekt abläuft
Es beginnt bei den Konsumenten. Schicken Sie uns, wer diese API aufruft, was damit gemacht wird und den einen Endpunkt, der die meisten Support-Tickets verursacht hat. Das reicht meist zum Schätzen.
Zurück kommt ein schriftlicher Leistungsumfang: die Endpunktliste, die Entscheidung zur Authentifizierung, die Versionierungsrichtlinie und was in die erste Phase gehört und was bewusst nicht. Er trägt einen Preis und ist das Dokument, auf das sich der Vertrag bezieht, damit das, was Sie unterschreiben, und das, was wir bauen, dasselbe sind.
Dann die Arbeit, in Ihrem Repository und Ihrem Review-Prozess. Die Spezifikation wird ab der ersten Phase generiert und veröffentlicht, Ihre Konsumenten lesen sie also, während die API noch entsteht.
Was Sie bekommen
Die API, die erzeugte Spezifikation veröffentlicht dort, wo Konsumenten sie erreichen, eine Testsuite, die die Autorisierungs-Negativfälle und die Grenzen der Seitenaufteilung abdeckt, Ratenbegrenzung pro Konsument konfiguriert, und eine schriftliche Versionierungsregel, die sagt, was Sie ohne Ankündigung ändern und was nicht.
Wo die API zu einer bestehenden Anwendung hinzukommt, bekommen Sie außerdem das, was diese Arbeit meist zutage fördert: eine Liste der Geschäftsregeln, die in Controllern wohnten, und wo sie jetzt wohnen, damit beide Eingänge übereinstimmen.
Sanctum oder Passport legt fest, wie sich Konsumenten authentifizieren, und das lässt sich viel leichter festlegen als später ändern. Die schwierigere Frage darunter ist, ob Laravel für diese API überhaupt die richtige Laufzeitumgebung ist. Und wenn die API vor allem mit der API eines anderen sprechen soll, passt Integration besser.
