أفضل الممارسات باستخدام خدمات واجهة برمجة التطبيقات للتحقق من صحة العنوان

خدمات الويب على "منصة خرائط Google" هي مجموعة من واجهات HTTP لخدمات Google التي توفّر بيانات جغرافية لتطبيقات الخرائط.

يوضِّح هذا الدليل بعض الممارسات الشائعة المفيدة لإعداد طلبات خدمة الويب ومعالجة ردود الخدمة. يُرجى الرجوع إلى دليل المطوّر للاطّلاع على المستندات الكاملة حول واجهة برمجة التطبيقات للتحقّق من العنوان.

ما المقصود بخدمة الويب؟

خدمات الويب في "منصة خرائط Google" هي واجهة لطلب بيانات "واجهة برمجة التطبيقات للخرائط" من الخدمات الخارجية واستخدام البيانات داخل تطبيقات "خرائط Google". وقد تم تصميم هذه الخدمات لاستخدامها مع الخريطة، وذلك وفقًا لقيود الترخيص الواردة في بنود خدمة "منصة خرائط Google".

تستخدم خدمات الويب لواجهات برمجة التطبيقات للخرائط طلبات HTTP(S) لعناوين URL محددة، من خلال تمرير معلمات عناوين URL و/أو بيانات POST بتنسيق JSON كوسيطات للخدمات. بشكل عام، تعرض هذه الخدمات بيانات في نص الاستجابة JSON لتحليلها و/أو معالجتها بواسطة تطبيقك.

تحقَّق من صحة عنوان عن طريق إرسال طلب HTTP POST إلى طريقة verifyAddress كما يلي:

https://addressvalidation.googleapis.com/v1:validateAddress

تمرير نص JSON إلى الطلب الذي يحدّد العنوان للتحقق من صحة

ملاحظة: تتطلب جميع تطبيقات واجهة برمجة التطبيقات للتحقّق من صحة العنوان الحصول على مصادقة. تعرَّف على المزيد من المعلومات عن بيانات اعتماد المصادقة.

الوصول عبر طبقة المقابس الآمنة/بروتوكول أمان طبقة النقل (TLS)

يجب استخدام HTTPS لجميع طلبات "منصة خرائط Google" التي تستخدم مفاتيح واجهة برمجة التطبيقات أو تحتوي على بيانات المستخدمين. قد يتم رفض الطلبات المقدَّمة عبر بروتوكول HTTP والتي تحتوي على بيانات حسّاسة.

إنشاء عنوان URL صالح

قد تظن أنّ عنوان URL "الصالح" واضح بذاته، ولكن الأمر ليس كذلك تمامًا. قد يحتوي عنوان URL الذي يتم إدخاله في شريط عناوين في متصفح مثلاً على رموز خاصة (مثل "上海+中國")؛ يحتاج المتصفح إلى ترجمة هذه الأحرف داخليًا إلى ترميز مختلف قبل الإرسال. وعلى غرار الرمز نفسه، قد يتعامل أي رمز ينشئ إدخال UTF-8 أو يقبله مع عناوين URL التي تتضمّن أحرف UTF-8 على أنّها "صالحة"، ولكنه قد يحتاج أيضًا إلى ترجمة هذه الأحرف قبل إرسالها إلى خادم ويب. تُعرف هذه العملية باسم ترميز عناوين URL أو ترميز النسبة المئوية.

الأحرف الخاصة

نحتاج إلى ترجمة رموز خاصة لأن جميع عناوين URL يجب أن تتوافق مع البنية المحدّدة في مواصفات معرِّف الموارد المنتظم (URI). ويعني ذلك أنّ عناوين URL يجب أن تحتوي فقط على مجموعة فرعية خاصة من حروف ASCII: الرموز الأبجدية الرقمية المألوفة وبعض الأحرف المحجوزة لاستخدامها كأحرف تحكّم ضمن عناوين URL. ويلخص هذا الجدول هذه الأحرف:

ملخّص الأحرف الصالحة لعناوين URL
تحديدالشخصياتاستخدام عنوان URL
أحرف أبجدية رقمية أ ب ج د ه ز ه ي ي ك l m n o p q r s u v x y z أ ب C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 5 6 3 7 السلاسل النصية واستخدام النظام (http) والمنفذ (8080) وما إلى ذلك
غير محجوز - _ . ~ سلاسل نصية
تم الحجز ! * ' ( ) ; : @ & = + $ , / ؟ % # [ ] أحرف التحكّم و/أو سلاسل النص

عند إنشاء عنوان URL صالح، يجب أن تتأكد من أنّه لا يتضمّن سوى الأحرف المعروضة في جدول "ملخّص أحرف عناوين URL الصالحة". بشكل عام، يؤدي إنشاء عنوان URL لاستخدام هذه المجموعة من الأحرف إلى حدوث مشكلتَين، إحداهما إغفال والأخرى للاستبدال:

  • الأحرف التي تريد التعامل معها موجودة خارج المجموعة أعلاه. على سبيل المثال، يجب ترميز الأحرف في اللغات الأجنبية مثل 上海+中國 باستخدام الأحرف المذكورة أعلاه. وفقًا للاصطلاح الشائع، يتم غالبًا تمثيل المسافات (غير المسموح بها ضمن عناوين URL) باستخدام علامة الجمع '+' أيضًا.
  • توجد الأحرف ضمن المجموعة أعلاه كأحرف محجوزة، ولكن يجب استخدامها حرفيًا. على سبيل المثال، يتم استخدام ? في عناوين URL للإشارة إلى بداية سلسلة طلب البحث. وإذا كنت تريد استخدام السلسلة "? and the Mysterions"، عليك ترميز الحرف '?'.

يتم ترميز جميع الأحرف المطلوب ترميزها بعنوان URL باستخدام '%' وقيمة سداسية عشرية مكونة من حرفين تتوافق مع حرف UTF-8. على سبيل المثال، سيتم ترميز 上海+中國 بتنسيق UTF-8 بعنوان URL بالصيغة %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. سيتم ترميز السلسلة ? and the Mysterians بعنوان URL بالتنسيق %3F+and+the+Mysterians أو %3F%20and%20the%20Mysterians.

الأحرف الشائعة التي تحتاج إلى ترميز

إليك بعض الأحرف الشائعة التي يجب ترميزها:

حرف غير آمن قيمة مشفّرة
مسافة %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

قد يكون تحويل عنوان URL تتلقّاه من البيانات التي يُدخلها المستخدم معقدًا أحيانًا. على سبيل المثال، قد يُدخِل المستخدم عنوانًا على النحو التالي: "شارع التحرير". بشكل عام، يجب إنشاء عنوان URL من أجزائه، مع التعامل مع أي إدخال للمستخدم كأحرف حرفية.

بالإضافة إلى ذلك، تقتصر عناوين URL على 16384 حرفًا لجميع خدمات الويب في "منصة خرائط Google" وواجهات برمجة تطبيقات الويب الثابتة. في معظم الخدمات، نادرًا ما يتم الاقتراب من عدد الأحرف المسموح به. ومع ذلك، تجدر الإشارة إلى أنّ بعض الخدمات تتضمّن معلَمات متعددة قد تؤدي إلى إنشاء عناوين URL طويلة.

استخدام Google APIs بشكل مهذب

يمكن لعملاء واجهة برمجة التطبيقات ذات التصميم السيئ وضع حمل زائد عن اللازم على كل من الإنترنت وخوادم Google. يحتوي هذا القسم على بعض أفضل الممارسات لعملاء واجهات برمجة التطبيقات. يمكن أن يساعدك اتّباع أفضل الممارسات هذه في تجنُّب حظر تطبيقك بسبب إساءة الاستخدام غير المقصودة لواجهات برمجة التطبيقات.

التراجع الأسي

في حالات نادرة، قد يحدث خطأ ما أثناء تقديم طلبك، فقد تتلقى رمز استجابة HTTP 4XX أو 5XX، أو قد يفشل اتصال TCP في مكان ما بين العميل وخادم Google. غالبًا ما يكون من المفيد إعادة محاولة الطلب حيث قد ينجح طلب المتابعة عندما فشل الأصلي. ومع ذلك، من المهم عدم تكرار إجراء الطلبات إلى خوادم Google بشكل متكرر. ويمكن أن يؤدي سلوك التكرار هذا إلى زيادة الحمل على الشبكة بين العميل وGoogle ما يتسبب في حدوث مشاكل للعديد من الأطراف.

والطريقة الأفضل هي إعادة المحاولة مع زيادة التأخيرات بين المحاولات. عادةً ما يزيد التأخير بعامل ضرب مع كل محاولة، وهو أسلوب يُعرف باسم التراجع الأسي.

على سبيل المثال، ضع في اعتبارك تطبيقًا يريد إرسال هذا الطلب إلى Time Zone API:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

يوضح مثال بايثون التالي كيفية إجراء الطلب باستخدام تراجع أسّي:

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

يجب أيضًا أن تحرص على عدم وجود رمز لإعادة المحاولة بمستوى أعلى في سلسلة استدعاءات التطبيقات يؤدي إلى تكرار الطلبات في تتابع سريع.

الطلبات المتزامنة

يمكن أن تبدو الأعداد الكبيرة من الطلبات المتزامنة إلى واجهات برمجة تطبيقات Google كهجوم لقطع الخدمة الموزعة (DDoS) على بنية Google الأساسية، وسيتم التعامل معها وفقًا لذلك. لتجنُّب حدوث ذلك، عليك التأكّد من عدم مزامنة طلبات البيانات من واجهة برمجة التطبيقات بين البرامج.

على سبيل المثال، يمكنك استخدام تطبيق يعرض الوقت في المنطقة الزمنية الحالية. من المحتمل أن يضبط هذا التطبيق منبهًا في نظام تشغيل العميل لإيقاظه في بداية الدقيقة حتى يتم تحديث الوقت المعروض. يجب ألا يُجري التطبيق أي طلبات بيانات من واجهة برمجة التطبيقات كجزء من المعالجة المرتبطة بهذا المنبّه.

يُعدّ إجراء طلبات بيانات من واجهة برمجة التطبيقات استجابةً لأحد التنبيهات الثابتة أمرًا سيئًا لأنّه يؤدي إلى مزامنة طلبات البيانات من واجهة برمجة التطبيقات مع بداية الدقيقة، حتى بين الأجهزة المختلفة، بدلاً من توزيعها بالتساوي على مدار الوقت. ينتج عن التطبيق ذو التصميم السيئ الذي يقوم بذلك قفزة في حركة المرور في المستويات العادية ستين مرة في بداية كل دقيقة.

بدلاً من ذلك، فإن أحد التصميمات الجيدة المحتملة هو ضبط منبه ثانٍ على وقت يتم اختياره عشوائيًا. وعندما ينشط هذا التنبيه الثاني التطبيق، يستدعي أي واجهات برمجة تطبيقات يحتاج إليها ويخزِّن النتائج. عندما يريد التطبيق تحديث عرضه في بداية الدقيقة، فإنه يستخدم النتائج المخزنة سابقًا بدلاً من استدعاء واجهة برمجة التطبيقات مرة أخرى. باستخدام هذا النهج، يتم توزيع طلبات بيانات واجهة برمجة التطبيقات بالتساوي على مدار الوقت. علاوة على ذلك، لا تؤخّر طلبات البيانات من واجهة برمجة التطبيقات العرض عند تحديث الشاشة.

بصرف النظر عن بداية الدقيقة، فإن أوقات المزامنة الشائعة الأخرى التي يجب أن تحرص على عدم استهدافها تكون في بداية ساعة، وأن تبدأ كل يوم في منتصف الليل.

معالجة الردود

يناقش هذا القسم كيفية استخراج هذه القيم ديناميكيًا من ردود خدمة الويب.

توفر خدمات الويب لخرائط Google ردودًا يسهل فهمها، ولكنها ليست سهلة الاستخدام. عند إجراء استعلام، بدلاً من عرض مجموعة من البيانات، ربما ترغب في استخراج بعض القيم المحددة. وبشكل عام، سترغب في تحليل الردود من خدمة الويب واستخراج القيم التي تهمك فقط.

يعتمد نظام التحليل الذي تستخدمه على ما إذا كنت تعرض الإخراج بتنسيق JSON. قد تتم معالجة استجابات JSON في شكل كائنات JavaScript في JavaScript نفسها على البرنامج.