PHP ini file_get_contents внешнего URL
Я использую следующую функцию PHP:
file_get_contents('http://example.com');
Каждый раз, когда я выполняю это на одном конкретном сервере, результат оказывается пустым. В то время как на других серверах всё работает нормально и возвращает содержимое страницы. Однако, если на сервере, где результат пустой, я использую функцию локально — без доступа к внешнему URL (например, file_get_contents('../simple/internal/path.html');), то она работает исправно.
Я почти уверен, что проблема связана с определенной конфигурацией в php.ini. Однако я не уверен, с какой именно настройкой может быть связано это поведение. Прошу помочь.
5 ответ(ов)
В дополнение к ответу Aillyn, вы можете использовать функцию, подобную приведенной ниже, чтобы эмулировать поведение file_get_contents:
function get_content($URL){
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $URL);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
echo get_content('http://example.com');
Эта функция использует библиотеку cURL для получения содержимого по заданному URL. Она инициализирует cURL-сеанс, устанавливает необходимые параметры, выполняет запрос и возвращает полученные данные. Такой подход может быть особенно полезен в тех случаях, когда функции file_get_contents не хватает или она отключена на сервере.
Для того чтобы отправить запрос к HTTPS-URL с помощью cURL, вам нужно убедиться, что у вас установлены необходимые библиотеки для поддержки HTTPS. В вашем примере кода можно использовать ту же логику, просто указывая HTTPS-URL.
Вот пример кода для выполнения запроса к серверу по HTTPS:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.your_external_website.com"); // Измените на ваш HTTPS-URL
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
if (curl_errno($ch)) {
// Если возникла ошибка, можно вывести ее
echo 'Ошибка cURL: ' . curl_error($ch);
} else {
// Если нет ошибок, выводим результат
echo $result;
}
curl_close($ch);
Обратите внимание:
Если ваш сервер использует самоподписанные сертификаты, вам может потребоваться отключить проверку сертификата. Однако это небезопасно и не рекомендуется для производственной среды. Вы можете добавить следующую настройку, но используйте ее с осторожностью:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);Убедитесь, что cURL поддерживает HTTPS. Если вы используете Windows, убедитесь, что библиотека OpenSSL установлена и
php.iniнастроен правильно.
Таким образом, просто замените http:// на https:// в URL и выполните вышеуказанный код, чтобы сделать запрос к HTTPS.
Ответы, представленные выше, решают проблему, но не объясняют странное поведение, о котором упоминал автор вопроса (OP). Данное объяснение может помочь тем, кто тестирует взаимодействие между сайтами в разработке, когда все эти сайты находятся на одном хосте (и одном виртуальном хосте; я работаю с Apache 2.4 и PHP 7.0).
Существует одна тонкость с file_get_contents(), с которой я столкнулся, и она абсолютно актуальна здесь, но не была обсуждена (вероятно, из-за того, что плохо задокументирована или вообще не задокументирована, судя по всему, либо описана в obscure whitepaper о модели безопасности PHP, которую мне не удалось найти).
Когда allow_url_fopen установлен в значение Off во всех соответствующих контекстах (например, /etc/php/7.0/apache2/php.ini, /etc/php/7.0/fpm/php.ini и т.д.), но allow_url_fopen установлен в значение On в контексте командной строки (т.е. /etc/php/7.0/cli/php.ini), вызовы к file_get_contents() для локального ресурса будут разрешены, и никаких предупреждений не будет выдано, таких как:
file_get_contents('php://input');
или
// Путь за пределами корня документа, к которому агент веб-сервера имеет разрешение на чтение. Например, для веб-сервера apache2 это может быть www-data, и файл по пути /etc/php/7.0/filetoaccess будет успешно прочитан, если www-data имеет разрешение на чтение этого файла
file_get_contents('<путь к файлу на локальной машине, к которому агент может получить доступ>');
или
// Относительный путь в том же корне документа
file_get_contents('data/filename.dat');
В заключение, ограничение allow_url_fopen = Off можно сравнить с правилом iptables в цепочке OUTPUT, где ограничение применяется только в случае попытки «выйти из системы» или «изменить контексты».
П. С. allow_url_fopen, установленный в On в контексте командной строки (т.е. /etc/php/7.0/cli/php.ini), был у меня на системе, но я подозреваю, что это не повлияло бы на объяснение, которое я предоставил, даже если бы это значение было установлено в Off, если, конечно, вы не тестируете, запуская свои скрипты из командной строки. Я не тестировал поведение с allow_url_fopen, установленным в Off в контексте командной строки.
Этот код позволяет сделать ссылки на внешние ресурсы абсолютными без необходимости редактирования файла php.ini.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.your_external_website.com");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
$result = preg_replace("#(<\s*a\s+[^>]*href\s*=\s*[\"'])(?!http)([^\"'>]+)([\"'>]+)#",'$1http://www.your_external_website.com/$2$3', $result);
echo $result;
?>
Объяснение кода:
- Инициализация cURL: С помощью
curl_init()создаем новый ресурс cURL. - Установка параметров:
CURLOPT_URLуказывает URL, по которому будем делать запрос.CURLOPT_HEADERотключает вывод заголовков.CURLOPT_RETURNTRANSFERзаставляетcurl_exec()возвращать результат в виде строки, а не выводить его сразу на экран.
- Выполнение запроса:
curl_exec($ch)отправляет запрос и возвращает ответ. - Закрытие cURL:
curl_close($ch)освобождает ресурсы, связанные с cURL. - Преобразование ссылок: Используем
preg_replace()для замены относительных ссылок на абсолютные, добавляя перед ними базовый URL. - Вывод результата:
echo $result;выводит окончательный HTML-код с исправленными ссылками.
Таким образом, все относительные ссылки на странице превращаются в абсолютные, что упрощает взаимодействие с внешним сайтом.
Чтобы включить allow_url_fopen через cPanel или WHM в секции PHP INI, выполните следующие шаги:
В cPanel:
- Войдите в вашу панель управления cPanel.
- Прокрутите вниз до секции "Software" и нажмите на "MultiPHP INI Editor".
- Выберите домен, для которого вы хотите изменить настройки.
- Найдите параметр
allow_url_fopenв списке. - Установите его значение в
On. - Нажмите на кнопку "Save" для сохранения изменений.
В WHM:
- Войдите в WHM.
- Найдите и откройте раздел "MultiPHP INI Editor" в меню.
- Выберите версию PHP, для которой хотите изменить настройку.
- Найдите строку с
allow_url_fopenи установите её значение вOn. - После внесения изменений нажмите "Apply" или "Save Changes".
Примечание:
После изменения значения, возможно, придется перезагрузить веб-сервер или PHP-FPM, чтобы изменения вступили в силу. Также проверьте, что у вас есть необходимые права для внесения изменений в настройки PHP.
Если вы столкнулись с какими-либо проблемами, убедитесь, что изменения действительно применились, проверив файл phpinfo().
Получить полный URL в PHP
Функции startsWith() и endsWith() в PHP
Как получить расширение файла в PHP?
Как читать большой файл построчно?
Почему нельзя вызывать абстрактные функции из абстрактных классов в PHP?