بهترین روش ها در استفاده از خدمات وب Roads API

سرویس‌های وب پلتفرم نقشه‌های Google مجموعه‌ای از رابط‌های HTTP به سرویس‌های Google هستند که داده‌های جغرافیایی را برای برنامه‌های نقشه‌های شما ارائه می‌کنند.

این راهنما برخی از روش‌های رایج مفید برای تنظیم درخواست‌های وب سرویس و پردازش پاسخ‌های سرویس را توضیح می‌دهد. برای مستندات کامل Roads API به راهنمای توسعه‌دهنده مراجعه کنید.

وب سرویس چیست؟

سرویس‌های وب پلتفرم Google Maps رابطی برای درخواست داده‌های Maps API از سرویس‌های خارجی و استفاده از داده‌های درون برنامه‌های Maps شما هستند. این سرویس‌ها برای استفاده همراه با نقشه طراحی شده‌اند، طبق محدودیت‌های مجوز در شرایط خدمات پلتفرم نقشه‌های Google.

سرویس‌های وب Maps API از درخواست‌های HTTP(S) به آدرس‌های اینترنتی خاص، ارسال پارامترهای URL و/یا داده‌های POST با فرمت JSON به عنوان آرگومان‌هایی برای سرویس‌ها استفاده می‌کنند. به طور کلی، این سرویس ها داده ها را در بدنه پاسخ به عنوان JSON برای تجزیه و/یا پردازش توسط برنامه شما برمی گرداند.

یک درخواست معمولی وب سرویس Roads API معمولاً به شکل زیر است:

https://roads.googleapis.com/v1/snapToRoads?parameters&key=YOUR_API_KEY

جایی که snapToRoads خدمات خاص درخواست شده را نشان می دهد. سایر خدمات جاده‌ها شامل nearestRoads و speedLimits است.

توجه : همه برنامه های Roads API نیاز به احراز هویت دارند. اطلاعات بیشتری در مورد اعتبار احراز هویت دریافت کنید.

دسترسی SSL/TLS

HTTPS برای همه درخواست‌های پلتفرم Google Maps که از کلیدهای API استفاده می‌کنند یا حاوی داده‌های کاربر هستند، لازم است. درخواست‌های ارسال شده از طریق HTTP که حاوی داده‌های حساس هستند ممکن است رد شوند.

ساخت یک URL معتبر

ممکن است فکر کنید که URL "معتبر" بدیهی است، اما کاملاً اینطور نیست. برای مثال، URL وارد شده در یک نوار آدرس در مرورگر، ممکن است حاوی کاراکترهای خاصی باشد (به عنوان مثال "上海+中國" ). مرورگر باید آن کاراکترها را به صورت داخلی قبل از انتقال به رمزگذاری دیگری ترجمه کند. به همین ترتیب، هر کدی که ورودی UTF-8 را تولید یا قبول می کند، ممکن است URL های دارای کاراکترهای UTF-8 را به عنوان "معتبر" تلقی کند، اما همچنین باید آن کاراکترها را قبل از ارسال به سرور وب ترجمه کند. این فرآیند کدگذاری URL یا رمزگذاری درصد نامیده می شود.

شخصیت های خاص

ما باید کاراکترهای ویژه را ترجمه کنیم زیرا همه URL ها باید با نحو مشخص شده توسط مشخصات Uniform Resource Identifier (URI) مطابقت داشته باشند. در واقع، این بدان معنی است که URL ها باید فقط شامل یک زیرمجموعه خاص از کاراکترهای ASCII باشند: نمادهای الفبایی عددی آشنا، و برخی از کاراکترهای رزرو شده برای استفاده به عنوان کاراکترهای کنترل در URL. این جدول به طور خلاصه این شخصیت ها را نشان می دهد:

خلاصه کاراکترهای URL معتبر
تنظیم کنید شخصیت ها استفاده از URL
الفبایی abcdefghijklm nopqrstuvwxyz ABCDEFGHIJKLM NOPQRSTUVWXYZ 0 1 2 3 4 5 6 7 8 9 رشته های متنی، استفاده از طرح ( http )، پورت ( 8080 )، و غیره.
بدون رزرو - _ . ~ رشته های متنی
رزرو شده است ! * ' ( ) ; : @ & = + $ , / ? % # [ ] کاراکترها و/یا رشته های متنی را کنترل کنید

هنگام ساختن یک URL معتبر، باید مطمئن شوید که فقط شامل کاراکترهای نشان داده شده در جدول باشد. تطبیق یک URL برای استفاده از این مجموعه از کاراکترها به طور کلی منجر به دو مشکل می شود، یکی حذف و دیگری جایگزینی:

  • کاراکترهایی که می خواهید آنها را مدیریت کنید خارج از مجموعه فوق وجود دارند. برای مثال، کاراکترهای زبان‌های خارجی مانند上海+中國باید با استفاده از کاراکترهای بالا کدگذاری شوند. طبق قرارداد رایج، فضاها (که در URL ها مجاز نیستند) اغلب با استفاده از کاراکتر '+' نیز نمایش داده می شوند.
  • کاراکترها در مجموعه فوق به عنوان کاراکترهای رزرو شده وجود دارند، اما باید به معنای واقعی کلمه استفاده شوند. به عنوان مثال ? در URL ها برای نشان دادن ابتدای رشته پرس و جو استفاده می شود. اگر می خواهید از رشته "? and the Mysterions" استفاده کنید، باید '?' را رمزگذاری کنید. شخصیت

همه کاراکترهایی که باید با URL رمزگذاری شوند با استفاده از یک کاراکتر '%' و یک مقدار هگز دو نویسه مطابق با نویسه UTF-8 کدگذاری می شوند. به عنوان مثال،上海+中國در UTF-8 به صورت %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ها برای همه سرویس‌های وب پلتفرم Google Maps و APIهای وب استاتیک به ۱۶۳۸۴ کاراکتر محدود می‌شوند. برای اکثر سرویس ها، به ندرت به این محدودیت شخصیت نزدیک می شود. با این حال، توجه داشته باشید که برخی از سرویس ها دارای چندین پارامتر هستند که ممکن است منجر به URL های طولانی شود.

استفاده مودبانه از Google API

کلاینت‌های API با طراحی ضعیف می‌توانند بار بیشتری را بر روی اینترنت و سرورهای Google قرار دهند. این بخش شامل برخی از بهترین شیوه ها برای مشتریان API است. پیروی از این بهترین شیوه ها می تواند به شما کمک کند تا از مسدود شدن برنامه خود به دلیل سوء استفاده ناخواسته از API ها جلوگیری کنید.

عقب نشینی نمایی

در موارد نادر ممکن است مشکلی در ارائه درخواست شما پیش بیاید. ممکن است یک کد پاسخ HTTP 4XX یا 5XX دریافت کنید، یا اتصال TCP ممکن است به سادگی در جایی بین کلاینت شما و سرور Google خراب شود. اغلب ارزش امتحان مجدد درخواست را دارد زیرا ممکن است درخواست پیگیری زمانی که درخواست اصلی با شکست مواجه شود موفق شود. با این حال، مهم است که به سادگی درخواست های مکرر را به سرورهای Google حلقه نکنید. این رفتار حلقه‌ای می‌تواند شبکه بین مشتری شما و Google را بیش از حد بارگذاری کند و برای بسیاری از طرف‌ها مشکل ایجاد کند.

یک رویکرد بهتر، تلاش مجدد با افزایش تاخیر بین تلاش ها است. معمولاً تأخیر با یک عامل ضربی با هر تلاش افزایش می‌یابد، رویکردی که به عنوان عقب‌نشینی نمایی شناخته می‌شود.

به عنوان مثال، برنامه‌ای را در نظر بگیرید که می‌خواهد این درخواست را به 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}")

همچنین باید مراقب باشید که در زنجیره فراخوانی برنامه کدی که به درخواست‌های مکرر پی در پی منجر می‌شود، کدی برای امتحان مجدد وجود نداشته باشد.

درخواست های همگام شده

تعداد زیادی از درخواست‌های همگام‌سازی‌شده به APIهای Google می‌توانند مانند حمله انکار سرویس توزیع‌شده (DDoS) به زیرساخت‌های Google به نظر برسند و مطابق با آن رفتار شود. برای جلوگیری از این امر، باید مطمئن شوید که درخواست‌های API بین کلاینت‌ها همگام‌سازی نمی‌شوند.

به عنوان مثال، برنامه ای را در نظر بگیرید که زمان را در منطقه زمانی فعلی نمایش می دهد. این برنامه احتمالاً زنگ هشداری را در سیستم عامل مشتری تنظیم می کند که آن را در ابتدای دقیقه بیدار می کند تا زمان نمایش داده شده به روز شود. برنامه نباید هیچ تماس API را به عنوان بخشی از پردازش مرتبط با آن زنگ برقرار کند.

برقراری تماس‌های API در پاسخ به زنگ هشدار ثابت بد است، زیرا باعث می‌شود که تماس‌های API با شروع دقیقه، حتی بین دستگاه‌های مختلف، به جای توزیع یکنواخت در طول زمان، همگام‌سازی شوند. یک برنامه با طراحی ضعیف که این کار را انجام می‌دهد، در شروع هر دقیقه یک ترافیک در سطح 60 برابر عادی ایجاد می‌کند.

در عوض، یکی از طرح‌های خوب ممکن این است که زنگ دوم را روی زمان انتخابی تصادفی تنظیم کنید. هنگامی که این زنگ دوم فعال می شود، برنامه هر API مورد نیاز خود را فراخوانی می کند و نتایج را ذخیره می کند. هنگامی که برنامه می خواهد نمایشگر خود را در ابتدای دقیقه به روز کند، به جای فراخوانی مجدد API از نتایج ذخیره شده قبلی استفاده می کند. با این رویکرد، فراخوانی های API در طول زمان به طور مساوی پخش می شوند. علاوه بر این، تماس‌های API هنگام به‌روزرسانی نمایشگر، رندر را به تأخیر نمی‌اندازند.

به غیر از شروع دقیقه، سایر زمان‌های همگام‌سازی معمولی که باید مراقب باشید در شروع یک ساعت و شروع هر روز در نیمه‌شب است.

پردازش پاسخ ها

در این بخش چگونگی استخراج این مقادیر به صورت پویا از پاسخ های سرویس وب بحث می شود.

سرویس‌های وب Google Maps پاسخ‌هایی را ارائه می‌دهند که به راحتی قابل درک هستند، اما دقیقاً کاربر پسند نیستند. هنگام انجام یک پرس و جو، به جای نمایش مجموعه ای از داده ها، احتمالاً می خواهید چند مقدار خاص را استخراج کنید. به طور کلی، شما می خواهید پاسخ ها را از وب سرویس تجزیه کنید و فقط مقادیری را استخراج کنید که مورد علاقه شما هستند.

طرح تجزیه ای که استفاده می کنید به این بستگی دارد که آیا خروجی را در JSON برمی گردانید یا خیر. پاسخ‌های JSON، که قبلاً به شکل اشیاء جاوا اسکریپت هستند، ممکن است در خود جاوا اسکریپت روی کلاینت پردازش شوند.