5 Dinge, die Sie noch nie mit einer REST-Spezifikation gemacht haben
Veröffentlicht: 2022-03-11Die meisten Frontend- und Backend-Entwickler haben sich schon einmal mit REST-Spezifikationen und RESTful-APIs beschäftigt. Aber nicht alle RESTful-APIs sind gleich. Tatsächlich sind sie überhaupt selten RESTful…
Was ist eine RESTful-API?
Es ist ein Mythos.
Wenn Sie glauben, dass Ihr Projekt über eine RESTful-API verfügt, liegen Sie höchstwahrscheinlich falsch. Die Idee hinter einer RESTful-API ist es, so zu entwickeln, dass alle Architekturregeln und -beschränkungen eingehalten werden, die in der REST-Spezifikation beschrieben sind. Realistischerweise ist dies in der Praxis jedoch weitgehend unmöglich.
Einerseits enthält REST zu viele verschwommene und mehrdeutige Definitionen. In der Praxis werden beispielsweise einige Begriffe aus den HTTP-Methoden- und Statuscode-Wörterbüchern zweckentfremdet oder gar nicht verwendet.
Andererseits schafft die REST-Entwicklung zu viele Einschränkungen. Beispielsweise ist die atomare Ressourcennutzung für reale APIs, die in mobilen Anwendungen verwendet werden, suboptimal. Die vollständige Verweigerung der Datenspeicherung zwischen Anfragen verbietet im Wesentlichen den „Benutzersitzungs“-Mechanismus, der fast überall zu sehen ist.
Aber warte, es ist nicht so schlimm!
Wofür benötigen Sie eine REST-API-Spezifikation?
Trotz dieser Nachteile ist REST mit einem vernünftigen Ansatz immer noch ein erstaunliches Konzept zum Erstellen wirklich großartiger APIs. Diese APIs können konsistent sein und eine klare Struktur, gute Dokumentation und eine hohe Unit-Test-Abdeckung aufweisen. All dies erreichen Sie mit einer hochwertigen API-Spezifikation .
Normalerweise ist eine REST-API-Spezifikation mit ihrer Dokumentation verbunden. Im Gegensatz zu einer Spezifikation – einer formalen Beschreibung Ihrer API – soll die Dokumentation für Menschen lesbar sein: zum Beispiel von den Entwicklern der Mobil- oder Webanwendung gelesen werden, die Ihre API verwendet.
Bei einer korrekten API-Beschreibung geht es nicht nur darum, die API-Dokumentation gut zu schreiben. In diesem Artikel möchte ich Beispiele dafür vorstellen, wie Sie:
- Machen Sie Ihre Unit-Tests einfacher und zuverlässiger;
- Einrichten der Vorverarbeitung und Validierung von Benutzereingaben;
- Automatisieren Sie die Serialisierung und stellen Sie die Konsistenz der Antworten sicher; und selbst
- Genießen Sie die Vorteile der statischen Eingabe.
Beginnen wir jedoch zunächst mit einer Einführung in die Welt der API-Spezifikationen.
OpenAPI
OpenAPI ist derzeit das am weitesten verbreitete Format für REST-API-Spezifikationen. Die Spezifikation wird in eine einzelne Datei im JSON- oder YAML-Format geschrieben, die aus drei Abschnitten besteht:
- Ein Header mit dem API-Namen, der Beschreibung und der Version sowie zusätzlichen Informationen.
- Beschreibungen aller Ressourcen, einschließlich Bezeichner, HTTP-Methoden, aller Eingabeparameter, Antwortcodes und Body-Datentypen, mit Links zu Definitionen.
- Alle Definitionen, die für Ein- oder Ausgabe verwendet werden können, im JSON-Schemaformat (das ja auch in YAML dargestellt werden kann.)
Die Struktur von OpenAPI hat zwei wesentliche Nachteile: Sie ist zu komplex und manchmal redundant. Ein kleines Projekt kann eine JSON-Spezifikation mit Tausenden von Zeilen haben. Die manuelle Pflege dieser Datei wird unmöglich. Dies ist eine erhebliche Bedrohung für die Idee, die Spezifikation während der Entwicklung der API auf dem neuesten Stand zu halten.
Es gibt mehrere Editoren, mit denen Sie eine API beschreiben und eine OpenAPI-Ausgabe erstellen können. Weitere Dienste und darauf basierende Cloud-Lösungen sind Swagger, Apiary, Stoplight, Restlet und viele andere.
Diese Dienste waren jedoch für mich aufgrund der Komplexität der schnellen Bearbeitung von Spezifikationen und deren Anpassung an Codeänderungen unpraktisch. Darüber hinaus war die Liste der Funktionen von einem bestimmten Dienst abhängig. So ist es beispielsweise nahezu unmöglich, vollwertige Unit-Tests auf Basis der Tools eines Cloud-Dienstes zu erstellen. Codegenerierung und Mocking von Endpunkten erscheinen zwar praktisch, erweisen sich in der Praxis jedoch als meist nutzlos. Dies liegt hauptsächlich daran, dass das Endpunktverhalten normalerweise von verschiedenen Dingen wie Benutzerberechtigungen und Eingabeparametern abhängt, die für einen API-Architekten offensichtlich sein können, aber nicht einfach automatisch aus einer OpenAPI-Spezifikation generiert werden können.
Tinyspec
In diesem Artikel werde ich Beispiele verwenden, die auf meinem eigenen REST-API-Definitionsformat, tinyspec , basieren. Definitionen bestehen aus kleinen Dateien mit einer intuitiven Syntax. Sie beschreiben Endpunkte und Datenmodelle, die in einem Projekt verwendet werden. Dateien werden neben dem Code gespeichert und bieten eine schnelle Referenz und die Möglichkeit, sie während des Schreibens des Codes zu bearbeiten. Tinyspec wird automatisch in ein vollwertiges OpenAPI-Format kompiliert, das sofort in Ihrem Projekt verwendet werden kann.
Ich werde auch Beispiele für Node.js (Koa, Express) und Ruby on Rails verwenden, aber die Praktiken, die ich demonstrieren werde, sind auf die meisten Technologien anwendbar, einschließlich Python, PHP und Java.
Wo die API-Spezifikation rockt
Nachdem wir nun einige Hintergrundinformationen haben, können wir untersuchen, wie Sie das Beste aus einer ordnungsgemäß spezifizierten API herausholen können.
1. Endpunkt-Einheitentests
Die verhaltensgesteuerte Entwicklung (BDD) ist ideal für die Entwicklung von REST-APIs. Am besten schreiben Sie Komponententests nicht für separate Klassen, Modelle oder Controller, sondern für bestimmte Endpunkte. In jedem Test emulieren Sie eine echte HTTP-Anforderung und überprüfen die Antwort des Servers. Für Node.js gibt es die Pakete supertest und chai-http zur Emulation von Anfragen, für Ruby on Rails Airborne.
Angenommen, wir haben ein User
und einen GET /users
-Endpunkt, der alle Benutzer zurückgibt. Hier ist eine TinySpec-Syntax, die dies beschreibt:
# user.models.tinyspec User {name, isAdmin: b, age?: i} # users.endpoints.tinyspec GET /users => {users: User[]}
Und so würden wir den entsprechenden Test schreiben:
Node.js
describe('/users', () => { it('List all users', async () => { const { status, body: { users } } = request.get('/users'); expect(status).to.equal(200); expect(users[0].name).to.be('string'); expect(users[0].isAdmin).to.be('boolean'); expect(users[0].age).to.be.oneOf(['boolean', null]); }); });
Rubin auf Schienen
describe 'GET /users' do it 'List all users' do get '/users' expect_status(200) expect_json_types('users.*', { name: :string, isAdmin: :boolean, age: :integer_or_null, }) end end
Wenn wir bereits die Spezifikation haben, die Serverantworten beschreibt, können wir den Test vereinfachen und einfach prüfen, ob die Antwort der Spezifikation entspricht. Wir können tinyspec-Modelle verwenden, von denen jedes in eine OpenAPI-Spezifikation umgewandelt werden kann, die dem JSON-Schemaformat folgt.
Jedes literale Objekt in JS (oder Hash
in Ruby, dict
in Python, assoziatives Array in PHP und sogar Map
in Java) kann auf JSON-Schema-Konformität validiert werden. Es gibt sogar entsprechende Plugins zum Testen von Frameworks, zum Beispiel jest-ajv (npm), chai-ajv-json-schema (npm) und json_matchers for RSpec (rubygem).
Bevor Sie Schemas verwenden, importieren wir sie in das Projekt. Generieren Sie zunächst die openapi.json
-Datei basierend auf der tinyspec-Spezifikation (Sie können dies automatisch vor jedem Testlauf tun):
tinyspec -j -o openapi.json
Node.js
Jetzt können Sie das generierte JSON im Projekt verwenden und daraus den definitions
abrufen. Dieser Schlüssel enthält alle JSON-Schemas. Schemas können Querverweise ( $ref
) enthalten. Wenn Sie also eingebettete Schemas haben (z. B. Blog {posts: Post[]}
), müssen Sie sie zur Verwendung in der Validierung auspacken. Dazu verwenden wir json-schema-deref-sync (npm).
import deref from 'json-schema-deref-sync'; const spec = require('./openapi.json'); const schemas = deref(spec).definitions; describe('/users', () => { it('List all users', async () => { const { status, body: { users } } = request.get('/users'); expect(status).to.equal(200); // Chai expect(users[0]).to.be.validWithSchema(schemas.User); // Jest expect(users[0]).toMatchSchema(schemas.User); }); });
Rubin auf Schienen
Das Modul json_matchers
weiß, wie es mit $ref
Referenzen umgeht, erfordert jedoch separate Schemadateien am angegebenen Speicherort, sodass Sie die Datei swagger.json
in mehrere kleinere Dateien aufteilen müssen:
# ./spec/support/json_schemas.rb require 'json' require 'json_matchers/rspec' JsonMatchers.schema_root = 'spec/schemas' # Fix for json_matchers single-file restriction file = File.read 'spec/schemas/openapi.json' swagger = JSON.parse(file, symbolize_names: true) swagger[:definitions].keys.each do |key| File.open("spec/schemas/#{key}.json", 'w') do |f| f.write(JSON.pretty_generate({ '$ref': "swagger.json#/definitions/#{key}" })) end end
So sieht der Test aus:
describe 'GET /users' do it 'List all users' do get '/users' expect_status(200) expect(result[:users][0]).to match_json_schema('User') end end
Das Schreiben von Tests auf diese Weise ist unglaublich bequem. Dies gilt insbesondere dann, wenn Ihre IDE das Ausführen von Tests und das Debuggen unterstützt (z. B. WebStorm, RubyMine und Visual Studio). Auf diese Weise können Sie die Verwendung anderer Software vermeiden, und der gesamte API-Entwicklungszyklus ist auf drei Schritte beschränkt:
- Entwerfen der Spezifikation in TinySpec-Dateien.
- Schreiben eines vollständigen Satzes von Tests für hinzugefügte/bearbeitete Endpunkte.
- Implementieren des Codes, der die Tests erfüllt.
2. Validierung der Eingabedaten
OpenAPI beschreibt nicht nur das Antwortformat, sondern auch die Eingabedaten. Auf diese Weise können Sie vom Benutzer gesendete Daten zur Laufzeit validieren und konsistente und sichere Datenbankaktualisierungen sicherstellen.
Angenommen, wir haben die folgende Spezifikation, die das Patchen eines Benutzerdatensatzes und aller verfügbaren Felder beschreibt, die aktualisiert werden dürfen:
# user.models.tinyspec UserUpdate !{name?, age?: i} # users.endpoints.tinyspec PATCH /users/:id {user: UserUpdate} => {success: b}
Zuvor haben wir die Plugins für die In-Test-Validierung untersucht, aber für allgemeinere Fälle gibt es die Validierungsmodule ajv (npm) und json-schema (rubygem). Lassen Sie uns sie verwenden, um einen Controller mit Validierung zu schreiben:
Node.js (Koa)
Dies ist ein Beispiel für Koa, den Nachfolger von Express – aber der entsprechende Express-Code würde ähnlich aussehen.
import Router from 'koa-router'; import Ajv from 'ajv'; import { schemas } from './schemas'; const router = new Router(); // Standard resource update action in Koa. router.patch('/:id', async (ctx) => { const updateData = ctx.body.user; // Validation using JSON schema from API specification. await validate(schemas.UserUpdate, updateData); const user = await User.findById(ctx.params.id); await user.update(updateData); ctx.body = { success: true }; }); async function validate(schema, data) { const ajv = new Ajv(); if (!ajv.validate(schema, data)) { const err = new Error(); err.errors = ajv.errors; throw err; } }
In diesem Beispiel gibt der Server die Antwort 500 Internal Server Error
zurück, wenn die Eingabe nicht der Spezifikation entspricht. Um dies zu vermeiden, können wir den Validierungsfehler abfangen und unsere eigene Antwort erstellen, die detailliertere Informationen zu bestimmten Feldern enthält, bei denen die Validierung fehlgeschlagen ist, und der Spezifikation folgen.
Lassen Sie uns die Definition für FieldsValidationError
:
# error.models.tinyspec Error {error: b, message} InvalidField {name, message} FieldsValidationError < Error {fields: InvalidField[]}
Und jetzt listen wir es als eine der möglichen Endpunktantworten auf:
# users.endpoints.tinyspec PATCH /users/:id {user: UserUpdate} => 200 {success: b} => 422 FieldsValidationError
Mit diesem Ansatz können Sie Komponententests schreiben, die die Korrektheit von Fehlerszenarien testen, wenn ungültige Daten vom Client kommen.
3. Modellserialisierung
Fast alle modernen Server-Frameworks verwenden auf die eine oder andere Weise objektrelationale Zuordnung (ORM). Dies bedeutet, dass die Mehrheit der von einer API verwendeten Ressourcen durch Modelle und ihre Instanzen und Sammlungen dargestellt werden.

Der Prozess der Erstellung der JSON-Darstellungen für diese in der Antwort zu sendenden Entitäten wird als Serialisierung bezeichnet.
Es gibt eine Reihe von Plugins für die Serialisierung: Zum Beispiel sequelize-to-json (npm), act_as_api (rubygem) und jsonapi-rails (rubygem). Grundsätzlich ermöglichen Ihnen diese Plugins, die Liste der Felder für ein bestimmtes Modell bereitzustellen, die im JSON-Objekt enthalten sein müssen, sowie zusätzliche Regeln. Beispielsweise können Sie Felder umbenennen und ihre Werte dynamisch berechnen.
Schwieriger wird es, wenn Sie mehrere verschiedene JSON-Darstellungen für ein Modell benötigen oder wenn das Objekt verschachtelte Entitäten – Assoziationen – enthält. Dann benötigen Sie Funktionen wie Vererbung, Wiederverwendung und Serializer-Verknüpfung.
Unterschiedliche Module bieten unterschiedliche Lösungen, aber überlegen wir mal: Kann die Spezifikation wieder helfen? Im Grunde sind alle Informationen über die Anforderungen an JSON-Darstellungen, alle möglichen Feldkombinationen, einschließlich eingebetteter Entitäten, bereits darin enthalten. Und das bedeutet, dass wir einen einzigen automatisierten Serialisierer schreiben können.
Lassen Sie mich das kleine Modul sequelize-serialize (npm) vorstellen, das dies für Sequelize-Modelle unterstützt. Es akzeptiert eine Modellinstanz oder ein Array und das erforderliche Schema und durchläuft es dann, um das serialisierte Objekt zu erstellen. Es berücksichtigt auch alle erforderlichen Felder und verwendet verschachtelte Schemas für die zugehörigen Entitäten.
Angenommen, wir müssen alle Benutzer mit Beiträgen im Blog, einschließlich der Kommentare zu diesen Beiträgen, von der API zurückgeben. Beschreiben wir es mit der folgenden Spezifikation:
# models.tinyspec Comment {authorId: i, message} Post {topic, message, comments?: Comment[]} User {name, isAdmin: b, age?: i} UserWithPosts < User {posts: Post[]} # blogUsers.endpoints.tinyspec GET /blog/users => {users: UserWithPosts[]}
Nun können wir mit Sequelize den Request bauen und das serialisierte Objekt zurückgeben, das genau der oben beschriebenen Spezifikation entspricht:
import Router from 'koa-router'; import serialize from 'sequelize-serialize'; import { schemas } from './schemas'; const router = new Router(); router.get('/blog/users', async (ctx) => { const users = await User.findAll({ include: [{ association: User.posts, required: true, include: [Post.comments] }] }); ctx.body = serialize(users, schemas.UserWithPosts); });
Das ist fast magisch, nicht wahr?
4. Statische Eingabe
Wenn Sie cool genug sind, um TypeScript oder Flow zu verwenden, haben Sie sich vielleicht schon gefragt: „Was ist mit meinen wertvollen statischen Typen?!“ Mit den Modulen sw2dts oder swagger-to-flowtype können Sie alle notwendigen statischen Typen auf Basis von JSON-Schemas generieren und in Tests, Controllern und Serializern verwenden.
tinyspec -j sw2dts ./swagger.json -o Api.d.ts --namespace Api
Jetzt können wir Typen in Controllern verwenden:
router.patch('/users/:id', async (ctx) => { // Specify type for request data object const userData: Api.UserUpdate = ctx.request.body.user; // Run spec validation await validate(schemas.UserUpdate, userData); // Query the database const user = await User.findById(ctx.params.id); await user.update(userData); // Return serialized result const serialized: Api.User = serialize(user, schemas.User); ctx.body = { user: serialized }; });
Und Tests:
it('Update user', async () => { // Static check for test input data. const updateData: Api.UserUpdate = { name: MODIFIED }; const res = await request.patch('/users/1', { user: updateData }); // Type helper for request response: const user: Api.User = res.body.user; expect(user).to.be.validWithSchema(schemas.User); expect(user).to.containSubset(updateData); });
Beachten Sie, dass die generierten Typdefinitionen nicht nur im API-Projekt, sondern auch in Clientanwendungsprojekten verwendet werden können, um Typen in Funktionen zu beschreiben, die mit der API arbeiten. (Darüber werden sich Angular-Entwickler besonders freuen.)
5. Umwandlung von Abfragezeichenfolgentypen
Wenn Ihre API aus irgendeinem Grund Anforderungen mit dem MIME-Typ application/x-www-form-urlencoded
anstelle von application/json
verarbeitet, sieht der Anforderungstext folgendermaßen aus:
param1=value¶m2=777¶m3=false
Dasselbe gilt für Abfrageparameter (z. B. in GET
Anforderungen). In diesem Fall erkennt der Webserver Typen nicht automatisch: Alle Daten werden im String-Format vorliegen, also erhalten Sie nach dem Parsen dieses Objekt:
{ param1: 'value', param2: '777', param3: 'false' }
In diesem Fall schlägt die Schemavalidierung der Anforderung fehl, sodass Sie die Formate der richtigen Parameter manuell überprüfen und sie in die richtigen Typen umwandeln müssen.
Wie Sie sich vorstellen können, können Sie dies mit unseren guten alten Schemas aus der Spezifikation tun. Nehmen wir an, wir haben diesen Endpunkt und das folgende Schema:
# posts.endpoints.tinyspec GET /posts?PostsQuery # post.models.tinyspec PostsQuery { search, limit: i, offset: i, filter: { isRead: b } }
So sieht die Anfrage an diesen Endpunkt aus:
GET /posts?search=needle&offset=10&limit=1&filter[isRead]=true
Schreiben wir die Funktion castQuery
, um alle Parameter in die erforderlichen Typen umzuwandeln:
function castQuery(query, schema) { _.mapValues(query, (value, key) => { const { type } = schema.properties[key] || {}; if (!value || !type) { return value; } switch (type) { case 'integer': return parseInt(value, 10); case 'number': return parseFloat(value); case 'boolean': return value !== 'false'; default: return value; } }); }
Eine umfassendere Implementierung mit Unterstützung für verschachtelte Schemas, Arrays und null
ist im Modul cast-with-schema (npm) verfügbar. Jetzt verwenden wir es in unserem Code:
router.get('/posts', async (ctx) => { // Cast parameters to expected types const query = castQuery(ctx.query, schemas.PostsQuery); // Run spec validation await validate(schemas.PostsQuery, query); // Query the database const posts = await Post.search(query); // Return serialized result ctx.body = { posts: serialize(posts, schemas.Post) }; });
Beachten Sie, dass drei der vier Codezeilen Spezifikationsschemas verwenden.
Empfohlene Vorgehensweise
Es gibt eine Reihe von Best Practices, denen wir hier folgen können.
Verwenden Sie separate Erstellungs- und Bearbeitungsschemas
Normalerweise unterscheiden sich die Schemas, die Serverantworten beschreiben, von denen, die Eingaben beschreiben und zum Erstellen und Bearbeiten von Modellen verwendet werden. Beispielsweise muss die Liste der in POST
und PATCH
Anforderungen verfügbaren Felder streng begrenzt sein, und PATCH
normalerweise alle Felder als optional gekennzeichnet. Die Schemata, die die Antwort beschreiben, können freier sein.
Wenn Sie CRUDL-Endpunkte automatisch generieren, verwendet tinyspec die Postfixes New
und Update
. User*
-Schemas können folgendermaßen definiert werden:
User {id, email, name, isAdmin: b} UserNew !{email, name} UserUpdate !{email?, name?}
Versuchen Sie, nicht dieselben Schemas für verschiedene Aktionstypen zu verwenden, um versehentliche Sicherheitsprobleme aufgrund der Wiederverwendung oder Vererbung älterer Schemas zu vermeiden.
Befolgen Sie Schema-Namenskonventionen
Der Inhalt derselben Modelle kann für verschiedene Endpunkte variieren. Verwenden Sie die Postfixes With*
und For*
in Schemanamen, um den Unterschied und den Zweck aufzuzeigen. In tinyspec können Modelle auch voneinander erben. Zum Beispiel:
User {name, surname} UserWithPhotos < User {photos: Photo[]} UserForAdmin < User {id, email, lastLoginAt: d}
Postfixes können variiert und kombiniert werden. Ihr Name muss dennoch die Essenz widerspiegeln und die Dokumentation einfacher lesbar machen.
Trennen von Endpunkten basierend auf dem Clienttyp
Häufig gibt derselbe Endpunkt je nach Clienttyp oder Rolle des Benutzers, der die Anfrage gesendet hat, unterschiedliche Daten zurück. Beispielsweise können die Endpunkte GET /users
und GET /messages
für Benutzer mobiler Anwendungen und Backoffice-Manager erheblich unterschiedlich sein. Die Änderung des Endpunktnamens kann Overhead sein.
Um denselben Endpunkt mehrmals zu beschreiben, können Sie seinen Typ in Klammern nach dem Pfad hinzufügen. Dies vereinfacht auch die Verwendung von Tags: Sie teilen die Endpunktdokumentation in Gruppen auf, von denen jede für eine bestimmte API-Client-Gruppe bestimmt ist. Zum Beispiel:
Mobile app: GET /users (mobile) => UserForMobile[] CRM admin panel: GET /users (admin) => UserForAdmin[]
REST-API-Dokumentationstools
Nachdem Sie die Spezifikation im TinySpec- oder OpenAPI-Format erhalten haben, können Sie eine ansprechende Dokumentation im HTML-Format generieren und veröffentlichen. Dies wird Entwickler, die Ihre API verwenden, glücklich machen, und es ist sicher besser, eine REST-API-Dokumentationsvorlage von Hand auszufüllen.
Abgesehen von den zuvor erwähnten Cloud-Diensten gibt es CLI-Tools, die OpenAPI 2.0 in HTML und PDF konvertieren, die auf jedem statischen Hosting bereitgestellt werden können. Hier sind einige Beispiele:
- bootprint-openapi (npm, standardmäßig in tinyspec verwendet)
- swagger2markup-cli (jar, es gibt ein Anwendungsbeispiel, wird in tinyspec Cloud verwendet)
- redoc-cli (npm)
- Widdershins (npm)
Haben Sie weitere Beispiele? Teile sie in den Kommentaren.
Obwohl OpenAPI 3.0 vor einem Jahr veröffentlicht wurde, wird es leider immer noch schlecht unterstützt, und ich konnte weder in Cloud-Lösungen noch in CLI-Tools geeignete Beispiele für darauf basierende Dokumentation finden. Aus dem gleichen Grund unterstützt tinyspec OpenAPI 3.0 noch nicht.
Veröffentlichung auf GitHub
Eine der einfachsten Möglichkeiten, die Dokumentation zu veröffentlichen, sind GitHub-Seiten. Aktivieren Sie einfach die Unterstützung für statische Seiten für Ihren /docs
-Ordner in den Repository-Einstellungen und speichern Sie die HTML-Dokumentation in diesem Ordner.
Sie können den Befehl zum Generieren der Dokumentation über tinyspec oder ein anderes CLI-Tool in Ihre Datei scripts/package.json
, um die Dokumentation nach jedem Commit automatisch zu aktualisieren:
"scripts": { "docs": "tinyspec -h -o docs/", "precommit": "npm run docs" }
Kontinuierliche Integration
Sie können die Dokumentationserstellung zu Ihrem CI-Zyklus hinzufügen und beispielsweise in Amazon S3 je nach Umgebung oder API-Version unter verschiedenen Adressen (wie /docs/2.0
, /docs/stable
und /docs/staging
) veröffentlichen.
Tinyspec-Wolke
Wenn Ihnen die tinyspec-Syntax gefällt, können Sie ein Early Adopter für tinyspec.cloud werden. Wir planen, einen darauf basierenden Cloud-Service und eine CLI für die automatisierte Bereitstellung von Dokumentationen mit einer großen Auswahl an Vorlagen und der Möglichkeit, personalisierte Vorlagen zu entwickeln, aufzubauen.
REST-Spezifikation: Ein wunderbarer Mythos
Die REST-API-Entwicklung ist wahrscheinlich einer der angenehmsten Prozesse in der Entwicklung moderner Web- und Mobildienste. Es gibt keinen Browser, kein Betriebssystem und keine Zoos in Bildschirmgröße, und alles liegt vollständig unter Ihrer Kontrolle, mit Ihren Fingerspitzen.
Dieser Prozess wird durch die Unterstützung für Automatisierung und aktuelle Spezifikationen noch einfacher. Eine API, die die von mir beschriebenen Ansätze verwendet, wird gut strukturiert, transparent und zuverlässig.
Die Quintessenz ist, wenn wir einen Mythos machen, warum dann nicht einen wunderbaren Mythos daraus machen?