تابع wp_remote_get ابزار استاندارد وردپرس برای ارسال درخواست‌های HTTP GET به APIهای خارجی و منابع راه دور است. این تابع یک لایه انتزاعی روی cURL و سایر کتابخانه‌های HTTP ایجاد می‌کند و امکان تنظیم timeout، هدرها، پارامترها و ریدایرکت را فراهم می‌سازد. استفاده درست از آن، از خطاهای بی‌صدا، تایم‌اوت‌های سرگردان و رفتار غیرمنتظره در اتصال API جلوگیری می‌کند. اشتباهات رایجی مانند نبود بررسی is_wp_error، نبود timeout و نبود تست می‌تواند به پایداری ضعیف و تجربه کاربری نامناسب منجر شود. تسلط بر این تابع برای اتصال API ضروری است و در افزونه‌نویسی حرفه‌ای کاربرد گسترده دارد.

چرا اتصال API در وردپرس حیاتی است؟

وردپرس به‌تنهایی یک سیستم بسته نیست. افزونه‌های حرفه‌ای معمولاً با سرویس‌های خارجی ارتباط برقرار می‌کنند: درگاه پرداخت، سرویس ایمیل، APIهای هوش مصنوعی، سرویس‌های تحلیلی، پلتفرم‌های پیام‌رسان و بسیاری موارد دیگر. برای این ارتباطات، تابع wp_remote_get ابزار استاندارد وردپرس است. این تابع به‌جای cURL مستقیم استفاده می‌شود چرا که سازگاری بیشتر، امنیت بهتر و امکان تنظیم دقیق‌تر را فراهم می‌کند.

تابع wp_remote_get چیست؟

تابع wp_remote_get() یک تابع هسته وردپرس است که در فایل wp-includes/http.php تعریف شده است. این تابع یک درخواست HTTP GET به URL مشخص ارسال می‌کند و پاسخ را به‌شکل آرایه یا WP_Error برمی‌گرداند. در پشت صحنه، این تابع از WP_Http استفاده می‌کند که خودش از cURL، Streams یا fsockopen بر پایه تنظیمات سرور استفاده می‌کند. این لایه انتزاعی، امکان نوشتن کد مستقل از محیط سرور را فراهم می‌کند. نکته مهم این است که این تابع مقدار پاسخ یا WP_Error برمی‌گرداند و هیچ خطایی را به‌صورت مستقیم نمایش نمی‌دهد. بررسی خروجی به عهده توسعه‌دهنده است.

امضای تابع و پارامترها

امضای این تابع به‌شکل زیر است:
function wp_remote_get( $url, $args = array() ) {
    $http = _wp_http_get_object();
    return $http->request( $url, $args );
}
پارامتر اول (url) آدرس کامل درخواست است. پارامتر دوم (args) آرایه‌ای از تنظیمات است. خروجی این تابع یا یک آرایه است (در حالت موفق) که شامل headers، body، response، cookies و filename است، یا یک شیء WP_Error در حالت خطا.

آرگومان‌های کلیدی args

پارامتر args می‌تواند شامل تنظیمات زیر باشد: - timeout: حداکثر زمان انتظار (پیش‌فرض ۵ ثانیه) - redirection: تعداد ریدایرکت‌های مجاز (پیش‌فرض ۵) - headers: هدرهای HTTP به‌شکل آرایه - body: پارامترهای پرس‌وجو در GET (به‌شکل آرایه یا رشته) - sslverify: بررسی گواهی SSL (پیش‌فرض true) - user-agent: رشته User-Agent - blocking: اگر false باشد، پاسخ بلافاصله برمی‌گردد بدون انتظار - cookies: کوکی‌ها به‌شکل آرایه - decompress: رمزگشایی خودکار (پیش‌فرض true) نمونه استفاده:
$response = wp_remote_get(
    'https://api.example.com/v1/posts',
    array(
        'timeout'    => 15,
        'headers'    => array(
            'Authorization' => 'Bearer ' . $api_key,
            'Accept'        => 'application/json',
        ),
        'body'       => array(
            'page'     => 1,
            'per_page' => 20,
        ),
        'sslverify'  => true,
    )
);
نکته مهم: هرگز sslverify را روی false نگذارید مگر در محیط توسعه. این تنظیم، سایت را در معرض حمله MITM قرار می‌دهد.

نقش timeout در پایداری

مقدار پیش‌فرض timeout در وردپرس ۵ ثانیه است. این مقدار برای اکثر APIها کافی است اما در برخی سناریوها باید تنظیم شود: - برای APIهای کند: ۱۵ تا ۳۰ ثانیه - برای APIهای سریع که تأخیر مهم است: ۳ تا ۵ ثانیه - برای درخواست‌های پس‌زمینه که پاسخ فوری نیاز نیست: ۱ تا ۲ ثانیه عدم تنظیم timeout مناسب می‌تواند به دو مشکل جدی منجر شود: - اگر timeout بسیار کوتاه باشد، درخواست‌های معتبر بی‌دلیل شکست می‌خورند - اگر timeout بسیار طولانی باشد، صفحه سایت برای کاربران معطل می‌ماند الگوی حرفه‌ای، تنظیم timeout متفاوت برای سناریوهای مختلف است:
function myplugin_fetch_api_data( $url ) {
    $response = wp_remote_get( $url, array(
        'timeout' => 15,
    ) );

    if ( is_wp_error( $response ) ) {
        $code = $response->get_error_code();
        if ( 'http_request_failed' === $code ) {
            // ممکن است timeout رخ داده باشد
            error_log( 'API request failed: ' . $response->get_error_message() );
        }
        return false;
    }

    return $response;
}

بررسی is_wp_error

یکی از پرتکرارترین اشتباهات، نبود بررسی is_wp_error است. اگر پاسخ خطا باشد و بدون بررسی از آن استفاده کنید، ممکن است خطای Fatal Error رخ دهد:
// اشتباه
$response = wp_remote_get( $url );
$body = wp_remote_retrieve_body( $response ); // اگر خطا باشد، این نادرست عمل می‌کند

// صحیح
$response = wp_remote_get( $url );
if ( is_wp_error( $response ) ) {
    return false;
}
$body = wp_remote_retrieve_body( $response );
همچنین باید کد وضعیت HTTP را بررسی کنید:
$response = wp_remote_get( $url );

if ( is_wp_error( $response ) ) {
    return false;
}

$status = wp_remote_retrieve_response_code( $response );
if ( 200 !== $status ) {
    return false;
}

$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
نکته مهم: استفاده از توابع wp_remote_retrieve_* برای دسترسی به بخش‌های مختلف پاسخ، از دسترسی مستقیم به آرایه امن‌تر است. راهنمای این توابع در صفحه wp_remote_post نیز آمده است.

کاربردهای عملی در افزونه

دریافت داده از API خارجی:
function myplugin_get_github_repos( $username ) {
    $cache_key = 'myplugin_github_' . md5( $username );
    $cached = get_transient( $cache_key );

    if ( false !== $cached ) {
        return $cached;
    }

    $url = sprintf(
        'https://api.github.com/users/%s/repos',
        rawurlencode( $username )
    );

    $response = wp_remote_get( $url, array(
        'timeout' => 15,
        'headers' => array(
            'Accept'     => 'application/vnd.github.v3+json',
            'User-Agent' => 'MyPlugin/1.0',
        ),
    ) );

    if ( is_wp_error( $response ) ) {
        return array();
    }

    $status = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $status ) {
        return array();
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( ! is_array( $data ) ) {
        return array();
    }

    set_transient( $cache_key, $data, HOUR_IN_SECONDS );

    return $data;
}
نکته مهم: کش کردن پاسخ API با set_transient از درخواست‌های مکرر جلوگیری می‌کند و سرعت را بهبود می‌بخشد. راهنمای این تابع در صفحه set_transient و صفحه get_transient آمده است.

کش کردن درخواست‌ها

یکی از مهم‌ترین اصول در اتصال API، کش کردن پاسخ است. بدون کش، هر بار بارگذاری صفحه یک درخواست جدید به API ارسال می‌شود که می‌تواند به محدودیت نرخ (Rate Limit) منجر شود. الگوی حرفه‌ای کش:
function myplugin_cached_api_call( $endpoint, $cache_duration = 3600 ) {
    $cache_key = 'myplugin_api_' . md5( $endpoint );
    $cached = get_transient( $cache_key );

    if ( false !== $cached ) {
        return $cached;
    }

    $response = wp_remote_get( $endpoint, array(
        'timeout' => 10,
    ) );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    $status = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $status ) {
        return false;
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( ! is_array( $data ) ) {
        return false;
    }

    set_transient( $cache_key, $data, $cache_duration );

    return $data;
}
نکته مهم: در صورت خطا، داده کش نمی‌شود. این رویکرد از قفل شدن داده خراب در کش جلوگیری می‌کند.

نکات امنیتی و اشتباهات رایج

اشتباه اول، نبود بررسی is_wp_error است. بدون این بررسی، خطاهای شبکه به خطاهای Fatal تبدیل می‌شوند. اشتباه دوم، نبود timeout مناسب است. timeout پیش‌فرض ۵ ثانیه برای برخی APIها کافی نیست. اشتباه سوم، غیرفعال کردن sslverify است. این تنظیم، امنیت اتصال را از بین می‌برد و سایت را در معرض MITM قرار می‌دهد. اشتباه چهارم، نبود escape در خروجی است. اگر داده API در HTML چاپ می‌شود، باید با esc_html یا wp_kses_post عبور کند. اشتباه پنجم، ذخیره مستقیم پاسخ در دیتابیس بدون اعتبارسنجی است. همیشه ساختار داده را بررسی کنید. اشتباه ششم، نبود کش است. بدون کش، API ممکن است با خطای Rate Limit مواجه شود. اشتباه هفتم، نبود لاگ‌گیری است. خطاهای API باید در لاگ سرور ثبت شوند تا در محیط تولید قابل ردیابی باشند. اشتباه هشتم، ارسال اطلاعات حساس در پارامترهای URL است. اطلاعات حساس باید در هدر یا بدنه POST ارسال شوند.

تحلیل فنی پیشرفته

در نگاه مهندسی، تابع wp_remote_get() یک نقطه معماری در لایه HTTP Client است که بر چند جنبه از سیستم اثر می‌گذارد. لایه اول لایه Abstraction است. این تابع یک انتزاع روی cURL، Streams و fsockopen ایجاد می‌کند و امکان نوشتن کد مستقل از محیط سرور را فراهم می‌کند. لایه دوم لایه Filterability است. وردپرس فیلتر pre_http_request را فراهم می‌کند که امکان دخالت در درخواست پیش از ارسال را می‌دهد. این ساختار در تست و در Mocking بسیار کاربردی است. لایه سوم لایه Performance است. تنظیم blocking => false امکان ارسال درخواست بدون انتظار برای پاسخ را فراهم می‌کند که در برخی سناریوها مفید است. لایه چهارم لایه Caching است. بدون کش، درخواست‌های مکرر می‌تواند به محدودیت نرخ منجر شود. ترکیب wp_remote_get با set_transient یک الگوی استاندارد است. لایه پنجم لایه Error Handling است. تابع WP_Error امکان انتقال دقیق خطاها را فراهم می‌کند. لایه ششم لایه SSL Security است. تنظیم sslverify => true امکان بررسی گواهی SSL سرور راه دور را فراهم می‌کند. لایه هفتم لایه Multisite است. در شبکه‌های Multisite، درخواست‌ها در هر سایت مستقل ارسال می‌شوند. لایه هشتم لایه Testing است. تست‌های واحد باید با Mock کردن pre_http_request انجام شوند تا نیازی به درخواست واقعی نباشد. مفاهیم پایه‌ای HTTP در HTTP در ویکی‌پدیا توضیح داده شده است. برای مطالعه بیشتر روی توابع مرتبط، می‌توانید به راهنمای wp_remote_post، راهنمای wp_remote_request، راهنمای wp_send_json، راهنمای set_transient، راهنمای get_transient و راهنمای esc_html مراجعه کنید.

پرسش‌های پرتکرار

تفاوت wp_remote_get و wp_remote_post چیست؟ اولی درخواست GET و دومی درخواست POST ارسال می‌کند. چرا باید is_wp_error را بررسی کنیم؟ بدون این بررسی، خطاهای شبکه به خطاهای Fatal تبدیل می‌شوند. آیا می‌توان sslverify را غیرفعال کرد؟ تنها در محیط توسعه و به‌صورت موقت. چطور از Rate Limit جلوگیری کنیم؟ با کش کردن پاسخ‌ها. آیا این تابع از HTTP/2 پشتیبانی می‌کند؟ در صورتی که cURL سرور پشتیبانی کند، بله.

نتیجه و مسیر ادامه

تابع wp_remote_get() ابزار استاندارد وردپرس برای ارسال درخواست‌های HTTP GET است. استفاده درست از آن یعنی تنظیم timeout مناسب، بررسی is_wp_error، بررسی کد وضعیت، کش کردن پاسخ و escape در خروجی. اشتباه‌های کوچک در این تابع اغلب به خطاهای بی‌صدا یا کندی سایت منجر می‌شوند. اگر این تابع را در پروژه‌ای واقعی به کار برده‌اید و رفتار غیرمنتظره‌ای دیده‌اید — به‌خصوص در اتصال به APIهای خارجی — تجربه‌تان می‌تواند راهگشای دیگران باشد. کدام بخش بیشترین زمان را از شما گرفت؟ دیدگاه خود را بنویسید.