В настоящее время я работаю над инструментом для интеграции ссылок различных социальных сетей:
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 не является популярной социальной сетью с действующим сертификатом (я не пользуюсь им лично, я только что создал аккаунт для тестирования)?
Спасибо за помощь,
Джонатан Родитель-Левеск из Монреаля
Я попытался создать самоподписанный сертификат для своей среды разработки (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"));
}
Я надеюсь, что это решение поможет кому-то,
Джонатан Родитель-Левеск из Монреаля
Других решений пока нет …