Несогласованная ошибка с API-интерфейсом Facebook Graph в PHP - Не удалось подключиться к порту graph.facebook.com 443: Время ожидания подключения

Я интегрирую опцию входа в Facebook на сайте, над которым я работаю, и я столкнулся с некоторой проблемой при обращении к Facebook API на PHP. Фактическая ошибка, которую я получаю, следующая:

Не удалось подключиться к порту graph.facebook.com 443: время ожидания подключения

Я проверил, что значение таймаута для вызовов curl корректно, я попытался проверить соединение непосредственно из командной строки сервера через SSH (правильно пинцет, кажется, что порт открыт и процессы прослушивают его и т.д.)., Однако, используя простой фрагмент curl, который я нашел в Интернете другими, у кого были подобные проблемы, мне удалось легко его протестировать, и кажется, что проблемы являются прерывистыми/непоследовательными: иногда он работает безупречно и быстро, а иногда он загружается в течение нескольких секунд и с ошибкой выше.

Я очень сомневаюсь, что ошибка на стороне Facebook, но я не могу понять, что я делаю неправильно. Я работал с SDK на Facebook раньше, и это первый раз, когда я вижу эту ошибку.

Кто-нибудь еще сталкивался с этой проблемой раньше и исправил ее?

Быстрое замечание: это первый раз, когда я работаю с Facebook в проекте, основанном на Symfony, - не думаю, что это важно в этом случае, но бросая его там на всякий случай.

Соответствующие фрагменты:

$fb = new \Facebook\Facebook(['app_id' => '[withheld]',
                                      'app_secret' => '[withheld]',
                                      'default_graph_version' => 'v2.10',]);
$fb->setDefaultAccessToken($accessToken); # Access token obtained from Facebook Login in JS, passed in post data.

try {
    $basic_info_response = $fb->get('/me?fields=id,first_name,last_name,email,website');

    if ($with_picture)
        $profile_picture_response = $fb->get('/me/picture?width=720&height=720');

    if ($with_friends)
        $friends_response = $fb->get('/me/friends');
}
catch(\Facebook\Exceptions\FacebookResponseException $e) {
    echo 'Graph returned an error: ' . $e->getMessage();
    exit;
}
catch(\Facebook\Exceptions\FacebookSDKException $e) {
    echo 'Facebook SDK returned an error: ' . $e->getMessage();
    exit;
}

В этом коде он терпит неудачу при любом вызове $fb- > get() - не всегда один и тот же, иногда на первом, иногда на изображении один, иногда на друзей.

[Обновление]

Ошибка по-прежнему происходит примерно на 90% моих звонков. Я попытался сделать завивки вызовов непосредственно на сервере через SSH (curl -v graph.facebook.com) и получил два следующих результата:

* Rebuilt URL to: graph.facebook.com/
*   Trying 31.13.91.2...
* TCP_NODELAY set
*   Trying 2a03:2880:f01b:1:face:b00c:0:1...
* TCP_NODELAY set
* Immediate connect fail for 2a03:2880:f01b:1:face:b00c:0:1: Network is unreachable
* Connected to graph.facebook.com (31.13.91.2) port 80 (#0)
> GET / HTTP/1.1
> Host: graph.facebook.com
> User-Agent: curl/7.50.2
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< WWW-Authenticate: OAuth "Facebook Platform" "invalid_request" "Unsupported get request. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api"
< Access-Control-Allow-Origin: *
< Pragma: no-cache
< Cache-Control: no-store
< x-fb-rev: 3274377
< Content-Type: application/json; charset=UTF-8
< x-fb-trace-id: A2OYZzFP3v8
< facebook-api-version: v2.4
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< Vary: Accept-Encoding
< X-FB-Debug: z9FEtq3Rlh8LyFn6pOIBZ5ZMCX+TY1jUD7iZ7ZRZ8/YGAsi035TbCP3qdBzqxDryvjJhKoKxnbAdvcxY/7r3Vg==
< Date: Mon, 04 Sep 2017 19:51:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
* Curl_http_done: called premature == 0
* Connection #0 to host graph.facebook.com left intact

и

* Rebuilt URL to: graph.facebook.com/
*   Trying 31.13.91.2...
* TCP_NODELAY set
* Connected to graph.facebook.com (31.13.91.2) port 80 (#0)
> GET / HTTP/1.1
> Host: graph.facebook.com
> User-Agent: curl/7.50.2
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< WWW-Authenticate: OAuth "Facebook Platform" "invalid_request" "Unsupported get request. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api"
< Access-Control-Allow-Origin: *
< Pragma: no-cache
< Cache-Control: no-store
< x-fb-rev: 3274377
< Content-Type: application/json; charset=UTF-8
< x-fb-trace-id: BrIDaH8D8D5
< facebook-api-version: v2.4
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< Vary: Accept-Encoding
< X-FB-Debug: tYvsf7Nn2PVnHFkV40UUddjQGKzPl8XKfdNeiqu1CXZck5WuUUlcG9hoCAZQrOX93uS19m2JpAEu9DJ/YhSIeg==
< Date: Mon, 04 Sep 2017 19:54:54 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
* Curl_http_done: called premature == 0
* Connection #0 to host graph.facebook.com left intact

Есть ли у кого-нибудь больше информации или возможных объяснений по этой проблеме?

Ответ 1

Как оказалось, жестко закодированный CURLOPT_CONNECTTIMEOUT установлен в Facebook SDK в дополнение к регулярному таймауту - это, казалось, вызывало проблему. Всякий раз, когда соединение между моим сервером и API-интерфейсом Facebook было слишком медленным (10 с +), он будет тайм-аут, потому что 10s является значением по умолчанию в SDK.

Я изменил это значение на значение по умолчанию cURL для этой опции, которое равно 300, и оно снова заработало. Это значение устанавливается в SDK Facebook в классе FacebookCurlHttpClient в методе openConnection.

Теперь, по какой причине соединение будет таким медленным в несколько раз, оно остается неизвестным, но, по крайней мере, оно больше не вылетает, когда это происходит.

Вы можете переопределить методы оболочки SDK cURL, как показано ниже: https://www.sammyk.me/how-to-inject-your-own-http-client-in-the-facebook-php-sdk-v5#customizing-the-curl-predefined-constants

Например, здесь мои переопределенные методы позволяют значительно больше периодов времени до истечения времени ожидания:

<?php

namespace AppBundle\Lib\Facebook;

class CustomCurlOptsHttpClient extends \Facebook\HttpClients\FacebookCurlHttpClient
{
    public function send($url, $method, $body, array $headers, $timeOut)
    {
        $timeOut *= 5;
        return parent::send($url, $method, $body, $headers, $timeOut);
    }

    public function openConnection($url, $method, $body, array $headers, $timeOut)
    {
        $timeOut *= 5;
        parent::openConnection($url, $method, $body, $headers, $timeOut);

        $options = [
            CURLOPT_CONNECTTIMEOUT => 300,
        ];

        $this->facebookCurl->setoptArray($options);
    }
}

Вы также можете использовать пакетные запросы в SDK Facebook, если у вас есть несколько запросов сделать один за другим. Это поможет ускорить процесс и не позволит вам попасть в таймауты.

Надеюсь, что это поможет кому-то еще, кто сталкивается с той же проблемой!

Ответ 2

Я не могу комментировать, но вы можете предоставить какой-то код? Будем рады помочь и отладить эту проблему.

Кроме того, API-интерфейс Facebook API возвращает эту ошибку, когда что-то блокирует ваш запрос. Например, file_get_contents заблокирован на многих серверах хостинга.

Вы также должны обработать ошибку.

Ответ 3

Вот пример фрагмента, который я использую и работаю хорошо для меня.

<?php    
include 'configs.php';
    include_once "Facebook/autoload.php";
    $swipe=1;
    $goto=null;
    try {
        if (!isset($_SESSION['FACEBOOK_SESSION_TOKEN'])) {
            $fb = new Facebook\Facebook([
                'app_id' => APP_ID,
                'app_secret' => APP_SECRET,
                'default_graph_version' => 'v2.5',
            ]);
            $helper = $fb->getRedirectLoginHelper();
            $permissions = ["user_about_me","publish_actions" , "user_photos"];
            $loginUrl = $helper->getLoginUrl( CALLBACK_URL ,  $permissions);
            $swipe=0;

        }
    }
    catch(Facebook\Exceptions\FacebookResponseException $e) {
        echo 'Graph returned an error: ' . $e->getMessage();
        exit;
    } catch(Facebook\Exceptions\FacebookSDKException $e) {
        echo 'Facebook SDK returned an error: ' . $e->getMessage();
        exit;
    }?>

config.php

<?php

    define("CALLBACK_URL", "http://{domain}/facebookredirect.php");
    define("RESULT_PAGE", "http://{domain}//profile.php");
    define("LOGIN_URI" , "http://{domain}//index.html");
    define("APP_ID" , "########");
    define("APP_SECRET" ,"#####");
   ?>

Кроме того, API-интерфейс Graph не имеет 100-процентного времени безотказной работы. Проверьте, правильно ли работает ваш локон.