2015-03-01 10 views
25

में एकाधिक एपीआई संस्करणों का समर्थन करें मैंने फ्लास्क और पायथन के साथ एक रीस्टफुल webservice डिज़ाइन करना शुरू किया और मैं सोच रहा हूं कि एक ही प्रोजेक्ट में एकाधिक API संस्करणों का समर्थन कैसे करेगा। मैं अनुरोध किया गया API संस्करण इस तरह URL में डालने की सोच रहा हूँ: मैं संस्करण एपीआई के 1.1 में एक और अंत बिंदु जोड़ सकते हैं और v1 से सब कुछ रखना चाहते हैं कुछ समय के बादफ्लास्क

/myapp/v1/Users 

जो परिवर्तन नहीं किया:

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

"उपयोगकर्ता" -endpoint वी 2 में बदल गई है:

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

और इतने पर ...

0,123,

this सवाल सबसे आसान तरीका शायद को देखते हुए कुछ इस तरह होगा:

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

लेकिन मैं कल्पना कर सकते हैं कि इस प्रत्येक नए एपीआई संस्करण के साथ बनाए रखने के लिए कठिन हो जाएगा। इसलिए मैं सोच रहा था कि फ्लास्क के साथ इसे प्राप्त करने के लिए कोई बेहतर (= बनाए रखने के लिए आसान और बेहतर संरचित) तरीका है?

उत्तर

47

मैं आपके द्वारा संदर्भित प्रश्न पर स्वीकृत उत्तर का लेखक हूं। मुझे लगता है कि /<version>/users दृष्टिकोण आपके जैसा कहने के लिए बहुत प्रभावी नहीं है। यदि आपको तीन या चार अलग-अलग संस्करणों का प्रबंधन करना है तो आप स्पेगेटी कोड के साथ समाप्त हो जाएंगे।

मैंने प्रस्तावित nginx विचार बेहतर है, लेकिन आपको दो अलग-अलग अनुप्रयोगों की मेजबानी करने की कमी है। उसके बाद मैं एक तीसरे विकल्प का उल्लेख करने के लिए चूक गया, जो प्रत्येक एपीआई संस्करण के लिए ब्लूप्रिंट का उपयोग करना है। यहाँ

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

आप एक api/common.py कि आम कार्यों को लागू करता है कि एपीआई की जरूरत के सभी संस्करणों: उदाहरण के लिए, निम्न एप्लिकेशन संरचना (बहुत स्पष्टता के लिए सरलीकृत) पर विचार करें। उदाहरण के लिए, आपके पास एक सहायक फ़ंक्शन (मार्ग के रूप में सजाया नहीं जा सकता) जो आपके /users रूट का जवाब देता है जो v1 और v1.1 में समान है।

प्रत्येक एपीआई संस्करण के लिए routes.py मार्गों को परिभाषित करता है, और जब आवश्यक हो तो डुप्लिकेटिंग तर्क से बचने के लिए common.py फ़ंक्शंस में कॉल करें। उदाहरण के लिए, अपने v1 और v1.1 routes.py हो सकता है:

from api import common 

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

नोट api.route। यहां api एक ब्लूप्रिंट है। ब्लूप्रिंट के रूप में लागू प्रत्येक एपीआई संस्करण को उचित संस्करण वाले यूआरएल के साथ सब कुछ गठबंधन करने में मदद करता है।

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') 

यह संरचना, क्योंकि यह रहता है सभी API संस्करण अलग है, फिर भी वे एक ही आवेदन के द्वारा सेवा कर रहे हैं बहुत अच्छा है: यहाँ एक उदाहरण ऐप सेटअप कोड है कि आवेदन उदाहरण में एपीआई ब्लूप्रिंट का आयात करता है। एक अतिरिक्त लाभ के रूप में, जब v1 का समर्थन रोकने के लिए समय आता है, तो आप उस संस्करण के लिए register_blueprint कॉल को हटा दें, अपने स्रोतों से v1 पैकेज हटाएं और आप कर चुके हैं।

अब, इन सभी के साथ, आपको वास्तव में अपने एपीआई को इस तरह से डिजाइन करने का प्रयास करना चाहिए जिससे संस्करण को संशोधित करने के जोखिम को कम किया जा सके। गौर करें कि नए मार्गों को जोड़ने के लिए एक नए एपीआई संस्करण की आवश्यकता नहीं है, नए मार्गों के साथ एक एपीआई बढ़ाने के लिए यह बिल्कुल ठीक है।और मौजूदा मार्गों में बदलाव कभी-कभी ऐसे तरीके से डिज़ाइन किए जा सकते हैं जो पुराने ग्राहकों को प्रभावित न करें। कभी-कभी एपीआई को संशोधित करने के लिए कम दर्दनाक होता है और चीजों को बदलने की अधिक स्वतंत्रता होती है, लेकिन आदर्श रूप से ऐसा अक्सर नहीं होता है।

+0

यह बहुत अच्छा काम कर रहा है, बहुत बहुत धन्यवाद! – Keeper

+0

क्या आप लापता टुकड़े उपलब्ध कराने पर ध्यान देंगे? ब्लूप्रिंट वास्तव में कहां बनाते हैं? किस फाइल में? और ब्लूप्रिंट तत्काल क्या दिखता है? धन्यवाद। – thecountofzero

+0

@thecountofzero यहां मेरी एक पुस्तक एपीआई ब्लूप्रिंट है, मेरी पुस्तक से: https://github.com/miguelgrinberg/flasky/tree/master/app/api_1_0 – Miguel