Узел js не может прочитать данные из запроса curl через php

#php #node.js #curl

#php #node.js #curl

Вопрос:

У меня проблема с чтением данных, которые я отправил через запрос curl в nodejs. С Postman все работает должным образом, но когда я пытаюсь отправить запрос через curl, api возвращает ошибку внутреннего сервера 500, и я не знаю, где ошибка.

итак, вот мой php-код

 private function curl($url, $post = false, $header = false)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    if ($post) {
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
    }
    curl_setopt($ch, CURLOPT_HEADER, [
        'Content-Type: application/json',
        'Accept: application/json',
        'Content-Length: ' . mb_strlen(json_encode($post))
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec ($ch);
    curl_close($ch);
    return $response;
}
  

итак, теперь я поделюсь с вами частью nodejs

 console.log(req.body)
    let content = req.body.content
    if (!content.length) {
        return res.status(401).send({message: 'content is required'})
    }
  

и вот информация из журнала

 { '{"content":"content information"}': '' }
  

2020-08-18T07:27:38.191100 00:00 приложение [web.1]: ошибка типа: не удается прочитать свойство ‘length’ неопределенного значения.
Я не знаю, в чем моя ошибка, и почему я не могу прочитать данные json на узле js, любая помощь будет оценена.

Ответ №1:

Я столкнулся с той же проблемой при попытке сделать это. Это можно решить, используя http_build_query($post) вместо json_encode . Если вы используете express JS, убедитесь, что у вас есть указанные ниже обработчики.

 app.use(express.urlencoded({ extended: false }));
app.use(express.json());
  

Ответ №2:

В вашем коде есть 2 заметных ошибки, и из-за дерьмовых оболочек libcurl в PHP php даже не предупреждает вас, когда замечает

 curl_setopt($ch, CURLOPT_HEADER, [
  

CURLOPT_HEADER решает, должен ли curl печатать полученные заголовки вместе с телом в выходных данных, и он даже не принимает массивы, он принимает bools (true / false / 0 / 1)

Если бы api был хорошо спроектирован, вы бы получили InvalidArgumentException or TypeError при предоставлении CURLOPT_HEADER чего-либо другого, кроме bool .. но поскольку он плохо спроектирован, php просто … «преобразует массив в bool» (что означает, что так и будет, false если массив пуст, или true иначе)

То, что вы на самом деле хотели здесь, это CURLOPT_HTTPHEADER опция для установки заголовков HTTP-запроса, принимающая массив.

Кроме того,

     'Content-Length: ' . mb_strlen(json_encode($post))
  

Это неправильно, во-первых, mb_strlen() выдает вам количество символов Юникода в строке, в то время как Content-Length заголовок должен содержать количество байтов, а не количество символов Юникода, поэтому он должен быть strlen(), а не mb_strlen().

Во-вторых, curl добавит этот заголовок автоматически, если вы его не добавите, а curl не допустит никаких опечаток и не вычислит длину неправильно, так что вам лучше просто позволить curl добавлять этот заголовок автоматически в любом случае (вы неправильно рассчитали длину, curl не допустит этой ошибки, также люди склонны вводить опечатки, у curl есть testsuites, чтобы убедиться, что в заголовке «Content-Length» нет опечаток, для сравнения.

Бьюсь об заклад, в вашем проекте нет тестовых наборов, чтобы убедиться, что вы не ввели никаких опечаток в Content-Length заголовок)

Ответ №3:

Может показаться, что вы неправильно добавляете тело к вашему запросу в php / curl. В результате req.body.content является undefined . Доступ к свойству на undefined выдает вашу ошибку, поэтому вам нужно проверить наличие такой возможности в вашем JS-коде, но реальная проблема в вашей системе заключается в том, что вы не отправляете тело на php. Надеюсь, это поможет вам добраться до корня проблемы, и вы сможете выяснить, как прикрепить данные тела к вашему запросу оттуда.

Комментарии:

1. да, в postman я использую необработанное содержимое json для отправки в запрос, хорошо, я попытаюсь отправить информацию через body, а не как необработанный объект json

2. нет, с телом запроса на самом деле все в порядке, проблема в том, что заголовки запроса неправильные (например, в «Content-Type» его запроса указано application/x-www-form-urlencoded , что выводит fsck из NodeJS)