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?