Проблема с запросами POST в PHP после миграции сервера

Недавно я перенес свой код, который был полностью работоспособен на предыдущем сервере, но на новом сервере запросы POST не работают, но запросы GET работают нормально. Кроме того, проблема возникает, когда я отправляю запросы POST на конечные точки на одном сервере. Когда я отправляю POST-запросы на внешние серверы, код работает хорошо. Во время отладки данные, отправляемые через (POST), не принимаются на конечной точке, а данные отправляются через cURL.

Я использую эту функцию для вызова конечных точек API:

function CallAPI($method = "GET", $url = "", $data = false, $credentials = "") {
    try {
        if (isset($url) && !empty($url)) {
            $curl = curl_init();

            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

            if (!empty($credentials)) {
                curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                curl_setopt($curl, CURLOPT_USERPWD, $credentials);
            }

            if ($method === "POST" || $method === "PUT") {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
            } else if ($method === "GET") {
                $url = sprintf("%s?%s", $url, http_build_query($data));
            }


            curl_setopt($curl, CURLOPT_TIMEOUT, 60);
            curl_setopt($curl, CURLOPT_URL, $url);

            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
            
            $response = curl_exec($curl);

            if ($response === false) {
                throw new Exception("cURL error: " . curl_error($curl));
            }

            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

            curl_close($curl);

            if ($httpCode < 200 || $httpCode >= 300) {
                throw new Exception("HTTP error: " . $httpCode);
            }

            return $response;
        } else {
            return false;
        }
    } catch (Exception $e) {
        // error_log("Error in CallAPI: " . $e->getMessage());
        return false; 
    }
}

В целях отладки я создал простой скрипт для простого вывода отправляемых данных:

<?php
  $response['status'] = "OK";
  $data = !empty($_POST) ? $_POST : file_get_contents("php://input");
  if (!empty($data)) {
    $phpArray = json_decode($data, true);
    $response['message'] = 'Data received successfully';
    $response['data'] = $phpArray;
  }
  $response['status'] = 'Endpoint successfully reached.';
  $response['method'] = $_SERVER['REQUEST_METHOD'];
  $response['rawdata'] = $data;
  echo json_encode($response);
  exit;
?>

Детали сервера

Previous Server:
CentOS 8
cPanel WHM
PHP 8.1

New Server:
CentOS 8
CyberPanel
PHP 8.1

Что я пробовал:

  1. Проверил, правильно ли установлен PHP.
  2. Проверил, что cURL и расширения установлены правильно.
  3. Пробовал отправлять POST-запросы на новый сервер с других серверов.

РЕДАКТИРОВАТЬ После дальнейшей отладки и исследования выяснилось, что проблема связана с отправляемыми данными, которые не были изменены до, во время и после миграции. Вот пример данных:

$msg = "<h3>Hello ".ucwords($name).",</h3> We received your quotation request.<br/>Thank you for your interest in our services.<br/>Your quotation has been generated and attached to this email.<br/>We look forward to providing you with our services.<br/><hr/><small>Please note that a 60% upfront payment may be required before services are provided.</small><br/><small>Please note that this message is an automated response.</small><br/><p><p>You may need to download a PDF viewer program such as Adobe PDF Reader in order to view the attached document or you may simply download the document on your device and open the file using your browser.</p><strong><h5>Regards</h5>Support Team</strong><br/></p>";

$invoice = array(
    "action" => "addQuote",
    "type" => "document",
    "ipaddress" => getIpAddress(),
    "customer" => array(
      "name" => $name,
      "email" => $email,
      "phone" => alphaNumeric($phone)
    ),
    "products" => $cart,
    "document" => array(
      "name" => "quotation",
      "date" => "",
      "currency" => "",
      "link" => ""
    ),
    "mail" => array(
      "subject" => $subject,
      "to" => $email,
      "bcc" => $info,
      "text" => $msg,
      "from" => $support,
      "entity" => "Example Entity"
    ),
    "sms" => array(
      "to" => $phone,
      "text" => "Hi ".ucwords($name).", Please find your quotation for requested services at $email. Thank you for your business.",
      "token" => "f4eb27cea7255cea4d1ffabf593372e8"
    ),
    "entity" => "5d14995453d10a56bd7c1d68"
);
$argv = json_encode(array("data" => $invoice));
  $document = CallAPI("POST", "https://api.endpoint.com/", $argv);
print_r($document);

Я начал с использования простых строковых данных, чтобы проверить, работают ли POST и cURL, и получил ответ от сервера. Затем я также попытался закомментировать часть свойств переменной $invoice. Я заметил, что когда я закомментирую либо msg в свойстве mail, либо text в свойстве sms, например, просто закомментирую любое из этих свойств, и сервер отправит ответ обратно.

Реализация: при входе в систему print_r(strlen($argv)); я понимаю, что мой код запускается и возвращает ответ только в том случае, если длина меньше или равна 1024.

Заставляет меня задаться вопросом:

  1. Возникла проблема с json_encode/json_decode. (Я также пробовал комбинацию htmlentities и json_encode, но безуспешно)
  2. Существует ограничение на количество данных, которые можно публиковать (я пробовал увеличить post_max_size в php.ini)

кто-нибудь еще сталкивался с этим? Есть ли способ решить эту проблему?

Вы можете использовать инструменты разработчика браузера, чтобы узнать, был ли отправлен POST-запрос. Если это так, вы знаете, что это проблема с получением.

KIKO Software 23.09.2023 13:45

Да, запрос отправляется, но ответ не отправляется.

Quatban Taco 23.09.2023 13:47

Итак, простой скрипт в вашем вопросе получает запрос POST, но не отображает его в выводе JSON?

KIKO Software 23.09.2023 13:49

Я заметил странный заголовок: Content-Typex, который должен быть: Content-Type?

KIKO Software 23.09.2023 13:50

@KIKOSoftware Да, это опечатка, которой нет на сервере. Но также скрипт не работает и не возвращает ответ независимо от указанного заголовка типа контента.

Quatban Taco 23.09.2023 14:26

Возможно, у вас есть ошибка в вашем простом тестовом сценарии. Например, когда $_SERVER['REQUEST_METHOD'] не определен. Вам также не нужен exit; в конце сценария. Вы можете проверить журнал ошибок PHP, чтобы увидеть, есть ли ошибки, или включить отчет об ошибках в выходных данных.

KIKO Software 23.09.2023 14:33

В журналах ошибок нет записей, и эти параметры также включены в код ini_set('display_errors', 1); ini_set('log_errors', 1); error_reporting(E_ALL);

Quatban Taco 23.09.2023 14:48
but no response is sent back....какой код статуса возвращается?
ADyson 23.09.2023 18:48

Возвращенный код состояния — 200. При дальнейшем расследовании выясняется, что проблема не в коде, а в передаваемых данных. Кстати, пересылаемые данные после миграции не изменились. я внесу правку в вопрос.

Quatban Taco 24.09.2023 11:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
9
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец я нашел ответ, и разница между серверами заключается в том, что на новом сервере, когда я POST-запрос с телом, клиент может включать заголовок «Ожидать: 100-продолжить». Этот заголовок сообщает серверу, что он должен ответить статусом «100 Продолжить» перед отправкой фактического тела запроса.

Чтобы решить эту проблему, я включил curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:')); в свою функцию CallAPI.

Вот моя обновленная функция CallAPI:

function CallAPI($method = "GET", $url = "", $data = false, $credentials = "") {
    try {
        if (isset($url) && !empty($url)) {
            $curl = curl_init();

            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

            if (!empty($credentials)) {
                curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                curl_setopt($curl, CURLOPT_USERPWD, $credentials);
            }

            if ($method === "POST" || $method === "PUT") {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            } else if ($method === "GET") {
                $url = sprintf("%s?%s", $url, http_build_query($data));
            }

            curl_setopt($curl, CURLOPT_TIMEOUT, 60);
            curl_setopt($curl, CURLOPT_URL, $url);

            curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:'));

            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
            
            $response = curl_exec($curl);

            if ($response === false) {
                throw new Exception("cURL error: " . curl_error($curl));
            }

            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

            curl_close($curl);

            if ($httpCode < 200 || $httpCode >= 300) {
                throw new Exception("HTTP error: " . $httpCode);
            }

            return $response;
        } else {
            return false;
        }
    } catch (Exception $e) {
        // error_log("Error in CallAPI: " . $e->getMessage());
        return false; 
    }
}

Другие вопросы по теме