2015-03-01 12 views
25

ho iniziato a progettare un webservice RESTful con la boccetta e Python e mi chiedo come si potrebbe supportare più versioni API nello stesso progetto. Sto pensando di mettere la versione API richiesto l'URL come questo:Supporto di più versioni API a pallone

/myapp/v1/Users 

Dopo qualche tempo voglio aggiungere un altro endpoint nella versione 1.1 delle API e tenere tutto da v1, che non cambiava:

/myapp/v1.1/Users <= Same as in v1 
/myapp/v1.1/Books 

in V2 il -endpoint "utenti" è cambiato:

/myapp/v2/Users <= Changed in v2 
/myapp/v2/Books <= Same as in v1.1 

e così via ...

0.123.

Guardando this discussione il modo più semplice, probabilmente sarebbe qualcosa di simile:

@app.route('/<version>/users') 
def users(version): 
    # do something 
    return jsonify(response) 

ma posso immaginare che questo otterrà più difficile da mantenere con ogni nuova versione API. Quindi mi chiedevo se c'è di meglio (= più facile da mantenere e meglio strutturata) modo per raggiungere questo obiettivo con Flask?

risposta

47

Io sono l'autore della risposta accettata sulla questione si fa riferimento. Penso che l'approccio /<version>/users non sia molto efficace come dici tu. Se devi gestire tre o quattro versioni differenti, finirai con il codice spaghetti.

L'idea nginx ho proposto non è meglio, ma ha lo svantaggio che si deve ospitare due applicazioni separate. A quel tempo mi mancava di menzionare una terza alternativa, che consiste nell'utilizzare un modello per ogni versione dell'API. Ad esempio, si consideri la seguente struttura app (molto semplificato per chiarezza):

my_project 
+-- api/ 
    +-- v1/ 
     +-- __init__.py 
     +-- routes.py 
    +-- v1_1/ 
     +-- __init__.py 
     +-- routes.py 
    +-- v2/ 
     +-- __init__.py 
     +-- routes.py 
    +-- __init__.py 
    +-- common.py 

Ecco una api/common.py che implementa funzioni comuni che tutte le versioni della necessità API. Ad esempio, si può avere una funzione ausiliaria (non decorato come un percorso) che risponde al vostro /users percorso che è identico in v1 e v1.1.

Il routes.py per ciascuna versione dell'API definisce i percorsi e, quando necessario, chiama nelle funzioni common.py per evitare la duplicazione della logica. Ad esempio, il v1 e v1.1 routes.py possono avere:

from api import common 

@api.route('/users') 
def get_users(): 
    return common.get_users() 

Annotare la api.route. Qui api è un progetto. L'implementazione di ciascuna versione dell'API come progetto aiuta a combinare tutto con gli URL con versione corretta. Ecco un codice di esempio di configurazione app che importa i progetti API nella istanza di applicazione:

from api.v1 import api as api_v1 
from api.v1_1 import api as api_v1_1 
from api.v2 import api as api_v2 

app.register_blueprint(api_v1, url_prefix='/v1') 
app.register_blueprint(api_v1_1, url_prefix='/v1.1') 
app.register_blueprint(api_v2, url_prefix='/v2') 

Questa struttura è molto bello perché mantiene tutte le versioni API separano, eppure sono serviti dalla stessa applicazione. Come ulteriore vantaggio, quando arriva il momento di smettere di supportare v1, basta rimuovere la chiamata register_blueprint per quella versione, eliminare il pacchetto v1 dai tuoi sorgenti e il gioco è fatto.

Ora, con tutto questo detto, si dovrebbe davvero fare uno sforzo per progettare la vostra API in modo da minimizzare il rischio di dover mandare su di giri la versione. Considera che l'aggiunta di nuovi percorsi non richiede una nuova versione dell'API, è perfettamente utile estendere un'API con nuove rotte.E i cambiamenti nelle rotte esistenti possono a volte essere progettati in modo da non influenzare i vecchi client. A volte è meno doloroso rivedere l'API e avere più libertà di cambiare le cose, ma idealmente ciò non accade troppo spesso.

+0

Questo funziona benissimo, grazie mille! – Keeper

+0

Ti dispiacerebbe fornire i pezzi mancanti? Dove vengono effettivamente creati i progetti? In quali file? E come si presenta l'istanza di Blueprint? Grazie. – thecountofzero

+0

@thecountofzero Ecco un esempio di modello API, dal mio libro: https://github.com/miguelgrinberg/flasky/tree/master/app/api_1_0 – Miguel

Problemi correlati