PHP get_headers () не работает с Pinterest

В настоящее время я работаю над инструментом для интеграции ссылок различных социальных сетей:

Facebook: https://www.facebook.com/jonathan.parentlevesque

Google plus: https://plus.google.com/+JonathanParentL%C3%A9vesque

Instagram: https://instagram.com/mariloubiz/

Pinterest: https://www.pinterest.com/jonathan_parl/

RSS: https://regex101.com

Twitter: https://twitter.com/arcadefire

Vimeo: https://vimeo.com/ondemand/crashtest/135301838

Youtube: https://www.youtube.com/user/Darkjo666

Я использую очень простое регулярное выражение, подобное этому:

/^https?:\/\/(?:[a-z]{2}|[w]{3})?\.pinterest.com\/[\S]{5,}$/i

на стороне клиента и сервера для минимальной проверки домена по каждой ссылке.

Затем я использую эту функцию для проверки того, что страница действительно существует (бесполезно интегрировать ссылки в социальных сетях, которые в конце концов не работают):

public static function isUrlExists($url){

$exists = false;

if(!StringManager::stringStartWith($url, "http") and !StringManager::stringStartWith($url, "ftp")){

$url = "https://" . $url;
}

if (preg_match(RegularExpression::URL, $url)){

$headers = get_headers($url);

if ($headers !== false and !empty($headers)){

if (strpos($headers[0], '404') === false){

$exists = true;
}
}
}

return $exists;
}

ЗаметкаВ этой функции я использую регулярное выражение Диего Перини для проверки URL перед отправкой запроса:

const URL = "%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu"; //@copyright Diego Perini

Все проверенные ссылки до сих пор не выдавали никаких ошибок, но тестирование Pinterest выдает мне довольно страшную серию сообщений об ошибках:

get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Array
(
[url] => https://www.pinterest.com/jonathan_parl/
[exists] =>
)

get_headers(): Failed to enable crypto

Array
(
[url] => https://www.pinterest.com/jonathan_parl/
[exists] =>
)

get_headers(https://www.pinterest.com/jonathan_parl/): failed to open stream: operation failed

Array
(
[url] => https://www.pinterest.com/jonathan_parl/
[exists] =>
)

У кого-нибудь есть идеи, что я тут делаю не так?

Я имею в виду, разве Pinterest не является популярной социальной сетью с действующим сертификатом (я не пользуюсь им лично, я только что создал аккаунт для тестирования)?

Спасибо за помощь,

Джонатан Родитель-Левеск из Монреаля

1

Решение

Я попытался создать самоподписанный сертификат для своей среды разработки (Xampp), как это было предложено N.B. в своем комментарии. Это решение не сработало для меня.

Его другим решением было использование cUrl или guzzle вместо get_headers (). Мало того, что это работало, но, согласно тестам этого разработчика:

http://php.net/manual/fr/function.get-headers.php#104723

это также намного быстрее, чем get_headers ().

Для тех, кто заинтересован, вот код моей новой функции:

/**
* Send an HTTP request to a the $url and check the header posted back.
*
* @param $url String url to which we must send the request.
* @param $failCodeList Int array list of codes for which the page is considered invalid.
*
* @return Boolean
*/
public static function isUrlExists($url, array $failCodeList = array(404)){

$exists = false;

if(!StringManager::stringStartWith($url, "http") and !StringManager::stringStartWith($url, "ftp")){

$url = "https://" . $url;
}

if (preg_match(RegularExpression::URL, $url)){

$handle = curl_init($url);


curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);

curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($handle, CURLOPT_HEADER, true);

curl_setopt($handle, CURLOPT_NOBODY, true);

curl_setopt($handle, CURLOPT_USERAGENT, true);


$headers = curl_exec($handle);

curl_close($handle);


if (empty($failCodeList) or !is_array($failCodeList)){

$failCodeList = array(404);
}

if (!empty($headers)){

$exists = true;

$headers = explode(PHP_EOL, $headers);

foreach($failCodeList as $code){

if (is_numeric($code) and strpos($headers[0], strval($code)) !== false){

$exists = false;

break;
}
}
}
}

return $exists;
}

Позвольте мне объяснить варианты скручивания:

CURLOPT_RETURNTRANSFER: вернуть строку вместо отображения страницы вызова на экране.

CURLOPT_SSL_VERIFYPEER: cUrl не будет проверять сертификат

CURLOPT_HEADER: включить заголовок в строку

CURLOPT_NOBODY: не включайте тело в строку

CURLOPT_USERAGENTНекоторые сайты нуждаются в этом для правильной работы (например: https://plus.google.com)


Дополнительное примечание: Я раскрываю строку заголовка и заголовки пользователя [0], чтобы убедиться, что проверяются только только код возврата и сообщение (пример: 200, 404, 405 и т. Д.)

Дополнительное примечание 2: Иногда проверки только кода 404 недостаточно (см. Модульный тест), поэтому есть необязательный параметр $ failCodeList для предоставления всего списка кодов для отклонения.

И, конечно же, вот модульный тест для легитимации моего кодирования:

public function testIsUrlExists(){

//invalid
$this->assertFalse(ToolManager::isUrlExists("woot"));

$this->assertFalse(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque4545646456"));

$this->assertFalse(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque890800"));

$this->assertFalse(ToolManager::isUrlExists("https://instagram.com/mariloubiz1232132/", array(404, 405)));

$this->assertFalse(ToolManager::isUrlExists("https://www.pinterest.com/jonathan_parl1231/"));

$this->assertFalse(ToolManager::isUrlExists("https://regex101.com/546465465456"));

$this->assertFalse(ToolManager::isUrlExists("https://twitter.com/arcadefire4566546"));

$this->assertFalse(ToolManager::isUrlExists("https://vimeo.com/**($%?%$", array(400, 405)));

$this->assertFalse(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666456456456"));


//valid
$this->assertTrue(ToolManager::isUrlExists("www.google.ca"));

$this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque"));

$this->assertTrue(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque"));

$this->assertTrue(ToolManager::isUrlExists("https://instagram.com/mariloubiz/"));

$this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque"));

$this->assertTrue(ToolManager::isUrlExists("https://www.pinterest.com/"));

$this->assertTrue(ToolManager::isUrlExists("https://regex101.com"));

$this->assertTrue(ToolManager::isUrlExists("https://twitter.com/arcadefire"));

$this->assertTrue(ToolManager::isUrlExists("https://vimeo.com/"));

$this->assertTrue(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666"));
}

Я надеюсь, что это решение поможет кому-то,

Джонатан Родитель-Левеск из Монреаля

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]