0

PHP ini file_get_contents внешнего URL

88

Я использую следующую функцию PHP:

file_get_contents('http://example.com');

Каждый раз, когда я выполняю это на одном конкретном сервере, результат оказывается пустым. В то время как на других серверах всё работает нормально и возвращает содержимое страницы. Однако, если на сервере, где результат пустой, я использую функцию локально — без доступа к внешнему URL (например, file_get_contents('../simple/internal/path.html');), то она работает исправно.

Я почти уверен, что проблема связана с определенной конфигурацией в php.ini. Однако я не уверен, с какой именно настройкой может быть связано это поведение. Прошу помочь.

5 ответ(ов)

0

В дополнение к ответу 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 не хватает или она отключена на сервере.

0

Для того чтобы отправить запрос к 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);

Обратите внимание:

  1. Если ваш сервер использует самоподписанные сертификаты, вам может потребоваться отключить проверку сертификата. Однако это небезопасно и не рекомендуется для производственной среды. Вы можете добавить следующую настройку, но используйте ее с осторожностью:

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    
  2. Убедитесь, что cURL поддерживает HTTPS. Если вы используете Windows, убедитесь, что библиотека OpenSSL установлена и php.ini настроен правильно.

Таким образом, просто замените http:// на https:// в URL и выполните вышеуказанный код, чтобы сделать запрос к HTTPS.

0

Ответы, представленные выше, решают проблему, но не объясняют странное поведение, о котором упоминал автор вопроса (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 в контексте командной строки.

0

Этот код позволяет сделать ссылки на внешние ресурсы абсолютными без необходимости редактирования файла 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;
?>

Объяснение кода:

  1. Инициализация cURL: С помощью curl_init() создаем новый ресурс cURL.
  2. Установка параметров:
    • CURLOPT_URL указывает URL, по которому будем делать запрос.
    • CURLOPT_HEADER отключает вывод заголовков.
    • CURLOPT_RETURNTRANSFER заставляет curl_exec() возвращать результат в виде строки, а не выводить его сразу на экран.
  3. Выполнение запроса: curl_exec($ch) отправляет запрос и возвращает ответ.
  4. Закрытие cURL: curl_close($ch) освобождает ресурсы, связанные с cURL.
  5. Преобразование ссылок: Используем preg_replace() для замены относительных ссылок на абсолютные, добавляя перед ними базовый URL.
  6. Вывод результата: echo $result; выводит окончательный HTML-код с исправленными ссылками.

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

0

Чтобы включить allow_url_fopen через cPanel или WHM в секции PHP INI, выполните следующие шаги:

В cPanel:

  1. Войдите в вашу панель управления cPanel.
  2. Прокрутите вниз до секции "Software" и нажмите на "MultiPHP INI Editor".
  3. Выберите домен, для которого вы хотите изменить настройки.
  4. Найдите параметр allow_url_fopen в списке.
  5. Установите его значение в On.
  6. Нажмите на кнопку "Save" для сохранения изменений.

В WHM:

  1. Войдите в WHM.
  2. Найдите и откройте раздел "MultiPHP INI Editor" в меню.
  3. Выберите версию PHP, для которой хотите изменить настройку.
  4. Найдите строку с allow_url_fopen и установите её значение в On.
  5. После внесения изменений нажмите "Apply" или "Save Changes".

Примечание:

После изменения значения, возможно, придется перезагрузить веб-сервер или PHP-FPM, чтобы изменения вступили в силу. Также проверьте, что у вас есть необходимые права для внесения изменений в настройки PHP.

Если вы столкнулись с какими-либо проблемами, убедитесь, что изменения действительно применились, проверив файл phpinfo().

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь