Практическое применение HTTP в PHP с примерами кода

Раздел: Программирование на PHP -> Сетевые соединения

HTTP соединения в PHP: обзор методов

Как выполнить HTTP запрос с полным контролем всех параметров?

Наиболее эффективным и гибким решением для работы с HTTP в PHP является расширение cURL. Оно поддерживает множество протоколов, позволяет настраивать заголовки, cookie, таймауты, работу с SSL сертификатами, а также выполнять POST, PUT и другие методы. cURL работает как с синхронными, так и с асинхронными запросами (через curl_multi).


<?php
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer token123']);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
if (curl_errno($ch)) {
    $error = curl_error($ch);
    // обработка ошибки
}
curl_close($ch);
?>
  

Php socket connection (сокетное соединение в php)

Типичные проблемы: неверный SSL сертификат (CURLOPT_SSL_VERIFYPEER), превышение времени ожидания (CURLOPT_TIMEOUT), ошибки DNS. Решение: установить CURLOPT_SSL_VERIFYPEER = false для тестовой среды, увеличить таймаут, проверить имя хоста.

Цель использования: когда требуется тонкая настройка запросов, поддержка различных протоколов, работа с большими объёмами данных или параллельные запросы.

Как сделать простой GET запрос без дополнительных библиотек?

Для простых GET запросов подходит встроенная функция file_get_contents. Она читает удалённый файл по URL, возвращает содержимое. Для настройки заголовков и других параметров требуется дополнительно создать потоковый контекст.


<?php
$url = 'https://api.example.com/data';
$response = file_get_contents($url);
if ($response === false) {
    // ошибка
}
?>
  

Php connect to server (подключение к php серверу)

Проблема: отсутствие контроля над запросом, невозможность отправки POST или настройки таймаута без stream_context. Для POST нужно использовать контекст.

Случаи использования: быстрые прототипы, чтение публичных данных, когда не нужны заголовки авторизации.

Как отправить POST запрос с заголовками используя только стандартные средства?

Функция stream_context_create позволяет задать контекст потока, включая HTTP метод, заголовки и тело запроса. Затем file_get_contents использует этот контекст.


<?php
$data = http_build_query(['key' => 'value']);
$options = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
                     "Authorization: Bearer token",
        'content' => $data,
        'timeout' => 10
    ]
];
$context = stream_context_create($options);
$response = file_get_contents('https://api.example.com/submit', false, $context);
?>
  

Http connection php (http-соединение в php)

Ошибки: неправильный синтаксис заголовков (требуется \r\n, не \n), некорректный content при JSON. Решение: использовать json_encode для JSON и устанавливать Content-Type: application/json.

Подходит для простых POST запросов без сложной обработки ответа.

Как установить соединение на низком уровне через сокеты?

Функция fsockopen открывает TCP сокет к хосту. Затем вручную формируется HTTP запрос и читается ответ. Полный контроль, но много ручной работы.


<?php
$fp = fsockopen('ssl://api.example.com', 443, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)\n";
} else {
    $out = "GET /data HTTP/1.1\r\n";
    $out .= "Host: api.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?>
  

Проблемы: необходимо разбирать HTTP ответ (отделять заголовки от тела), обрабатывать chunked encoding, управлять buffering. Очень легко ошибиться.

Используется только для обучения или в крайних случаях, когда нужна максимальная производительность на уровне сокетов.

Расширенные примеры HTTP соединений в PHP

Пример 1: cURL с обработкой ошибок и SSL

Полный GET запрос с проверкой сертификата и обработкой таймаута.

Пример

<?php
$ch = curl_init('https://jsonplaceholder.typicode.com/posts/1');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_CAINFO => '/path/to/cacert.pem',
    CURLOPT_TIMEOUT => 5,
    CURLOPT_USERAGENT => 'PHP cURL'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
    echo 'Ошибка cURL: ' . curl_error($ch);
} elseif ($httpCode !== 200) {
    echo "HTTP код: $httpCode";
} else {
    echo $response;
}
curl_close($ch);
?>
{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit..."
}

Пример 2: POST запрос с JSON через cURL

Пример

<?php
$data = json_encode(['title' => 'foo', 'body' => 'bar', 'userId' => 1]);
$ch = curl_init('https://jsonplaceholder.typicode.com/posts');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data)
    ],
    CURLOPT_TIMEOUT => 10
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
echo "HTTP статус: " . $info['http_code'] . "\n";
echo $response;
?>
HTTP статус: 201
{
  "title": "foo",
  "body": "bar",
  "userId": 1,
  "id": 101
}

Пример 3: file_get_contents с контекстом для POST с JSON

Пример

<?php
$data = json_encode(['name' => 'John']);
$options = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\n" .
                     "Accept: application/json\r\n",
        'content' => $data,
        'ignore_errors' => true
    ]
];
$context = stream_context_create($options);
$result = file_get_contents('https://httpbin.org/post', false, $context);
if ($result === false) {
    echo 'Ошибка запроса';
} else {
    echo $result;
}
?>
{
  "args": {},
  "data": "{\"name\":\"John\"}",
  "files": {},
  "form": {},
  ...
}

Пример 4: параллельные запросы через curl_multi

Пример

<?php
$urls = [
    'https://api.github.com/users/octocat',
    'https://api.github.com/users/defunkt',
    'https://api.github.com/users/mojombo'
];
$multiHandle = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_USERAGENT => 'PHP'
    ]);
    curl_multi_add_handle($multiHandle, $ch);
    $handles[$i] = $ch;
}
$running = null;
do {
    curl_multi_exec($multiHandle, $running);
} while ($running > 0);
foreach ($handles as $i => $ch) {
    $response = curl_multi_getcontent($ch);
    $info = curl_getinfo($ch);
    echo "URL $i: HTTP " . $info['http_code'] . "\n";
    // парсим ответ...
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}
curl_multi_close($multiHandle);
?>
URL 0: HTTP 200
URL 1: HTTP 200
URL 2: HTTP 200

Пример 5: fsockopen с полным разбором ответа

Пример

<?php
$host = 'example.com';
$port = 80;
$fp = fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) {
    die("$errstr ($errno)");
}
$request = "GET / HTTP/1.1\r\n" .
           "Host: $host\r\n" .
           "Connection: close\r\n\r\n";
fwrite($fp, $request);
$response = '';
while (!feof($fp)) {
    $response .= fgets($fp, 4096);
}
fclose($fp);
// Разделяем заголовки и тело
list($headers, $body) = explode("\r\n\r\n", $response, 2);
echo "Заголовки:\n$headers\n\n";
echo "Тело (первые 200 символов):\n" . substr($body, 0, 200);
?>
Заголовки:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
...

Тело (первые 200 символов):
<!doctype html>
<html>
<head>
...

HTTP-соединение в PHP - comments

En
Http connection php (php)