Oryginalna forma tej odpowiedzi jest zupełnie inna i można ją znaleźć tutaj . To tylko dowód, że istnieje więcej niż jeden sposób na oskórowanie kota.
Od tamtej pory zaktualizowałem odpowiedź, aby używać przestrzeni nazw i przekierowań 301 - zamiast domyślnego 302. Dzięki pixeltrix i Bo Jeanes za podpowiadanie tych rzeczy.
Możesz chcieć nosić naprawdę mocny kask, ponieważ to oszaleje .
Interfejs API routingu Rails 3 jest super zły. Aby napisać trasy dla swojego interfejsu API, zgodnie z powyższymi wymaganiami, potrzebujesz tylko tego:
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
Jeśli po tym momencie twój umysł jest nadal nienaruszony, pozwól mi wyjaśnić.
Po pierwsze, wywołujemy, namespace
co jest bardzo przydatne, gdy chcesz, aby grupa tras obejmowała określoną ścieżkę i moduł o podobnej nazwie. W tym przypadku chcemy, aby wszystkie trasy wewnątrz bloku namespace
były ograniczone do kontrolerów w Api
module, a wszystkie żądania do ścieżek wewnątrz tej trasy będą poprzedzone prefiksem api
. Prośby takie jak /api/v2/users
, wiesz?
Wewnątrz przestrzeni nazw definiujemy jeszcze dwie przestrzenie nazw (woah!). Tym razem mamy do definiowania nazw „v1”, więc tutaj wszystkie trasy dla kontrolerów będzie wewnątrz V1
modułu wewnątrz Api
modułu: Api::V1
. Definiując resources :users
wewnątrz tej trasy, kontroler będzie zlokalizowany pod adresem Api::V1::UsersController
. To jest wersja 1 i możesz się tam dostać, wykonując żądania, takie jak /api/v1/users
.
Wersja 2 jest tylko maleńki nieco inna. Zamiast kontrolera obsługującego to jest Api::V1::UsersController
teraz, jest teraz Api::V2::UsersController
. Dostajesz się tam, składając prośby takie jak /api/v2/users
.
Następnie match
używany jest. Spowoduje to dopasowanie wszystkich tras API, które prowadzą do rzeczy takich jak /api/v3/users
.
To jest ta część, na którą musiałem spojrzeć. :to =>
Opcja pozwala na określenie, że wniosek powinien zostać przekierowany specyficzny gdzieś indziej - Wiedziałem, że dużo - ale nie wiem jak zrobić to przekierować do innego miejsca i przekazać w kawałku pierwotnego wniosku wraz z nim .
Aby to zrobić, wywołujemy redirect
metodę i przekazujemy jej ciąg znaków ze specjalnym %{path}
parametrem interpolowanym . Kiedy przychodzi żądanie, które pasuje do tego końcowego match
, interpoluje path
parametr do lokalizacji %{path}
wewnątrz ciągu i przekierowuje użytkownika do miejsca, w którym musi się udać.
Na koniec używamy innego match
do kierowania wszystkich pozostałych ścieżek z prefiksem /api
i przekierowywania do nich /api/v2/%{path}
. Oznacza to, że żądania takie jak /api/users
trafią do /api/v2/users
.
Nie mogłem wymyślić, jak się /api/asdf/users
dopasować, ponieważ jak określisz, czy to ma być prośba o /api/<resource>/<identifier>
czy /api/<version>/<resource>
?
W każdym razie było to fajne badanie i mam nadzieję, że ci pomoże!
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.
Kilka rzeczy do dodania:
Twoje dopasowanie przekierowania nie zadziała na niektórych trasach -
*api
parametr jest chciwy i pochłonie wszystko, np./api/asdf/users/1
Przekieruje do/api/v2/1
. Lepiej byłoby użyć zwykłego parametru, takiego jak:api
. Wprawdzie nie będzie pasować do przypadków takich jak,/api/asdf/asdf/users/1
ale jeśli masz zagnieżdżone zasoby w swoim api, jest to lepsze rozwiązanie.Ryan DLACZEGO NIE LUBISZ
namespace
? :-), np .:Co ma dodatkową zaletę w postaci wersjonowanych i ogólnych nazwanych tras. Dodatkowa uwaga - konwencja podczas używania
:module
polega na używaniu notacji podkreślenia, np .:api/v1
nie „Api :: V1”. W pewnym momencie ta ostatnia nie działała, ale wydaje mi się, że została naprawiona w Railsach 3.1.Ponadto, gdy wydasz wersję 3 swojego API, trasy zostaną zaktualizowane w następujący sposób:
Oczywiście jest prawdopodobne, że Twój interfejs API ma różne trasy między wersjami, w takim przypadku możesz to zrobić:
źródło
/api/asdf/users?
jak również/api/users/1
? Nie mogłem tego rozgryźć w mojej zaktualizowanej odpowiedzi, więc pomyślałem, że możesz znać sposóbJeśli to w ogóle możliwe, sugerowałbym przemyślenie swoich adresów URL, tak aby wersja nie była w adresie URL, ale została umieszczona w nagłówku accept. Ta odpowiedź na przepełnienie stosu pasuje do tego dobrze:
Najlepsze praktyki dotyczące wersjonowania API?
a ten link pokazuje dokładnie, jak to zrobić z routingiem rails:
http://freelancing-gods.com/posts/versioning_your_ap_is
źródło
Nie jestem wielkim fanem wersjonowania trasami. Stworzyliśmy VersionCake, aby wspierać łatwiejszą formę wersjonowania API.
Umieszczając numer wersji API w nazwie pliku każdego z naszych odpowiednich widoków (jbuilder, RABL itp.), Utrzymujemy wersjonowanie dyskretne i pozwalamy na łatwą degradację w celu wsparcia kompatybilności wstecznej (np. Jeśli widok v5 nie istnieje, możemy render v4 widoku).
źródło
Nie jestem pewien, dlaczego chcesz przekierować do określonej wersji, jeśli wersja nie jest wyraźnie wymagana. Wygląda na to, że chcesz po prostu zdefiniować domyślną wersję, która będzie wyświetlana, jeśli żadna wersja nie zostanie wyraźnie zażądana. Zgadzam się również z Davidem Bockiem, że utrzymywanie wersji poza strukturą adresu URL jest czystszym sposobem obsługi wersjonowania.
Shameless plug: Versionist obsługuje te przypadki użycia (i nie tylko).
https://github.com/bploetz/versionist
źródło
Odpowiedź Ryana Bigga zadziałała dla mnie.
Jeśli chcesz również zachować parametry zapytania przez przekierowanie, możesz to zrobić w następujący sposób:
źródło
Zaimplementowałem to dzisiaj i znalazłem to, co uważam za „właściwą drogę” na RailsCasts - REST API Versioning . Tak prosty. Tak łatwe do utrzymania. Tak skuteczny.
Dodaj
lib/api_constraints.rb
(nie musisz nawet zmieniać vnd.example.)Konfiguracja
config/routes.rb
taka jak taEdytuj swój kontroler (tj.
/controllers/api/v1/squads_controller.rb
)Następnie możesz zmienić wszystkie linki w swojej aplikacji z
/api/v1/squads
na/api/squads
i ŁATWO wdrażać nowe wersje API bez konieczności zmiany linkówźródło