Die ursprüngliche Form dieser Antwort ist völlig anders und kann hier gefunden werden . Nur ein Beweis dafür, dass es mehr als einen Weg gibt, eine Katze zu häuten.
Ich habe die Antwort seitdem aktualisiert, um Namespaces zu verwenden und 301-Weiterleitungen zu verwenden - anstelle der Standardeinstellung 302. Vielen Dank an Pixeltrix und Bo Jeanes für die Aufforderung zu diesen Dingen.
Vielleicht möchten Sie einen wirklich starken Helm tragen, da dies Sie umhauen wird .
Die Rails 3-Routing-API ist super böse. Um die Routen für Ihre API gemäß Ihren obigen Anforderungen zu schreiben, benötigen Sie genau Folgendes:
namespace :api do
namespace :v1 do
resources :users
end
namespace :v2 do
resources :users
end
match 'v:api/*path', :to => redirect("/api/v2/%{path}")
match '*path', :to => redirect("/api/v2/%{path}")
end
Wenn Ihr Geist nach diesem Punkt noch intakt ist, lassen Sie mich das erklären.
Zunächst rufen wir an, namespace
was sehr praktisch ist, wenn Sie eine Reihe von Routen für einen bestimmten Pfad und ein bestimmtes Modul mit ähnlichen Namen wünschen. In diesem Fall möchten wir, dass alle Routen innerhalb des Blocks für namespace
Controller innerhalb des Api
Moduls festgelegt werden und allen Anforderungen an Pfade innerhalb dieser Route ein Präfix vorangestellt wird api
. Anfragen wie /api/v2/users
, weißt du?
Innerhalb des Namespace definieren wir zwei weitere Namespaces (woah!). Dieses Mal definieren wir den Namespace "v1", sodass sich alle Routen für die Controller hier innerhalb des V1
Moduls innerhalb des Api
Moduls befinden : Api::V1
. Durch die Definition resources :users
innerhalb dieser Route befindet sich der Controller unter Api::V1::UsersController
. Dies ist Version 1, und Sie gelangen dorthin, indem Sie Anfragen wie stellen /api/v1/users
.
Version 2 ist nur ein kleines bisschen anders. Anstelle des Controllers, der es bedient, Api::V1::UsersController
ist es jetzt bei Api::V2::UsersController
. Sie gelangen dorthin, indem Sie Anfragen wie stellen /api/v2/users
.
Als nächstes wird a match
verwendet. Dies entspricht allen API-Routen, die zu Dingen wie gehen /api/v3/users
.
Dies ist der Teil, den ich nachschlagen musste. Mit dieser :to =>
Option können Sie festlegen, dass eine bestimmte Anforderung an eine andere Stelle umgeleitet werden soll - das wusste ich -, aber ich wusste nicht, wie ich sie an eine andere Stelle umleiten und einen Teil der ursprünglichen Anforderung zusammen mit dieser weiterleiten kann .
Dazu rufen wir die redirect
Methode auf und übergeben ihr einen String mit einem speziell interpolierten %{path}
Parameter. Wenn eine Anforderung eingeht, die diesem Finale entspricht match
, interpoliert sie den path
Parameter in die Position %{path}
innerhalb der Zeichenfolge und leitet den Benutzer dorthin weiter, wo er hin muss.
Schließlich verwenden wir einen anderen match
, um alle verbleibenden Pfade, denen das Präfix vorangestellt ist, weiterzuleiten /api
und an diese umzuleiten /api/v2/%{path}
. Dies bedeutet, dass Anfragen wie /api/users
an gehen /api/v2/users
.
Ich konnte nicht herausfinden, wie ich /api/asdf/users
zum Match kommen kann, denn wie bestimmen Sie, ob dies eine Anfrage an /api/<resource>/<identifier>
oder sein soll /api/<version>/<resource>
?
Wie auch immer, es hat Spaß gemacht zu recherchieren und ich hoffe es hilft dir!
Please note that this redirection is a 301 “Moved Permanently” redirect. Keep in mind that some web browsers or proxy servers will cache this type of redirect, making the old page inaccessible.
Ein paar Dinge hinzuzufügen:
Ihr Weiterleitungs-Match funktioniert für bestimmte Routen nicht - der
*api
Parameter ist gierig und verschluckt alles, z . B./api/asdf/users/1
leitet er weiter/api/v2/1
. Sie sollten einen normalen Parameter wie verwenden:api
. Zugegeben, es passt nicht zu Fällen wie,/api/asdf/asdf/users/1
aber wenn Sie verschachtelte Ressourcen in Ihrer API haben, ist es eine bessere Lösung.Ryan WARUM MÖGEN SIE NICHT
namespace
? :-), z.B:Welches den zusätzlichen Vorteil von versionierten und generischen benannten Routen hat. Ein zusätzlicher Hinweis - die Konvention bei der Verwendung
:module
ist die Verwendung der Unterstrichnotation, z. B.:api/v1
Nicht 'Api :: V1'. Letzteres hat irgendwann nicht funktioniert, aber ich glaube, es wurde in Rails 3.1 behoben.Wenn Sie Version 3 Ihrer API veröffentlichen, werden die Routen wie folgt aktualisiert:
Natürlich ist es wahrscheinlich, dass Ihre API unterschiedliche Routen zwischen den Versionen hat. In diesem Fall können Sie dies tun:
quelle
/api/asdf/users?
so gut wie/api/users/1
? Ich konnte das in meiner aktualisierten Antwort nicht herausfinden, also dachte ich mir, dass Sie vielleicht einen Weg kennenWenn möglich, würde ich vorschlagen, Ihre URLs zu überdenken, damit die Version nicht in der URL enthalten ist, sondern in den Accept-Header eingefügt wird. Diese Antwort auf den Stapelüberlauf passt gut dazu:
Best Practices für die API-Versionierung?
und dieser Link zeigt genau, wie das mit Schienenführung gemacht wird:
http://freelancing-gods.com/posts/versioning_your_ap_is
quelle
Ich bin kein großer Fan von Routenversionen. Wir haben VersionCake entwickelt , um eine einfachere Form der API-Versionierung zu unterstützen.
Indem wir die API-Versionsnummer in den Dateinamen jeder unserer jeweiligen Ansichten (jbuilder, RABL usw.) aufnehmen, behalten wir die Versionsverwaltung unauffällig bei und ermöglichen eine einfache Verschlechterung, um die Abwärtskompatibilität zu unterstützen (z. B. wenn v5 der Ansicht nicht vorhanden ist, sind wir es v4 der Ansicht rendern).
quelle
Ich bin nicht sicher, warum Sie zu einer bestimmten Version umleiten möchten, wenn eine Version nicht explizit angefordert wird. Anscheinend möchten Sie einfach eine Standardversion definieren, die bereitgestellt wird, wenn keine Version explizit angefordert wird. Ich stimme auch David Bock zu, dass das Heraushalten von Versionen aus der URL-Struktur eine sauberere Möglichkeit ist, die Versionierung zu unterstützen.
Schamloser Plug: Versionist unterstützt diese Anwendungsfälle (und mehr).
https://github.com/bploetz/versionist
quelle
Die Antwort von Ryan Bigg hat bei mir funktioniert.
Wenn Sie auch Abfrageparameter über die Umleitung beibehalten möchten, können Sie dies folgendermaßen tun:
quelle
Habe dies heute implementiert und festgestellt, was meiner Meinung nach der richtige Weg für RailsCasts ist - REST API Versioning . So einfach. So wartbar. So effektiv.
Hinzufügen
lib/api_constraints.rb
(muss nicht einmal vnd.example ändern.)Setup
config/routes.rb
soBearbeiten Sie Ihren Controller (dh
/controllers/api/v1/squads_controller.rb
)Dann können Sie alle Links in Ihrer App von
/api/v1/squads
bis ändern/api/squads
und EINFACH neue API-Versionen implementieren, ohne die Links ändern zu müssenquelle