【问题标题】:Unexpected end of input when sending request from nodejs to php从nodejs向php发送请求时输入意外结束
【发布时间】:2023-03-15 12:16:01
【问题描述】:

因此,我查看了具有相同错误的其他答案,但他们的解决方案都没有回答我的问题。

我有一个 mysql 表,其中有大约 10k 个名称,并且我有一个 nodejs 文件的 25 个实例(侦听不同的端口),每个实例都发送请求以通过 php 文件从数据库中获取 400 个名称。如果我将请求设置为像 100 - 150 一样抓取它工作,但如果我告诉它获取超过 200,我会收到错误输入意外结束”。

这是我的 nodejs 请求:

function user_acquire()
{ 
var request = require('request');
var http = require('http');  

    var post_options = {
        host: 'localhost',
        path: '/name_request.php?pos1=50&pos2=150', //this is where the amount to request is set & range
        method: 'POST',
        headers: {
            'User-Agent': 'Super Agent/0.0.1',
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    };            


// Set up the request
    var post_req = http.request(post_options, function (res) {
        res.on('data', function (chunk) {
            usernames = JSON.parse(chunk);
        });
    });
    post_req.end(); 
}

这是 nodejs 与之通信的 php 文件:

<?php

$servername = "localhost"; 
$username = "root"; 
$password = ""; 
$dbname = "test"; 

$conn = new mysqli($servername, $username, $password, $dbname, '3306');
if ($conn->connect_error) 
{
    die("Connection failed: " . $conn->connect_error);
}

$start = $_GET['pos1'];
$end = $_GET['pos2'];

$sql = mysqli_query($conn, "SELECT * FROM preliminary_tests WHERE ID BETWEEN   '$start' AND '$end'");
$array = mysqli_fetch_all($sql, MYSQLI_ASSOC);
print_r(json_encode($array,JSON_UNESCAPED_UNICODE));

?>

使用JSON_UNESCAPED_UNICODE并不能解决问题。我知道 mysql 编码为utf-8这两个函数都适用于较小的请求,但增加请求大小会破坏一个,我不知道为什么

【问题讨论】:

  • 也许在 200 个用户名之后响应变得太大并且在发送到节点时被分成多个块。看起来您正在解析到达时的每个块,但该块可能会过早地切断 JSON,这就是您收到错误的原因。您应该能够在到达响应的“数据”事件时附加每个块,并在响应以它的“结束”事件结束时解析它们。
  • @Stiliyan 你如何建议我通过数据事件附加它们,我有一个粗略的想法?
  • 您应该能够通过在res.on('data') 回调上方声明var usernames = ""; 来使用闭包。 usernames 现在将在“数据”回调的范围内,您可以在其中附加传入的块 usernames += chunk;。然后,监听响应的结束事件,并在其回调中解析用户名。比如:res.on("end", function() { usernames = JSON.parse(usernames);})
  • @Stiliyan 你是这个意思吗? var post_req = http.request(post_options, function (res) { var usernames= " "; res.on("end", function () { usernames = JSON.parse(usernames); }); });
  • 您需要数据和结束回调。我决定把我的 cmets 变成一个答案。希望它有用,祝你好运!

标签: php mysql node.js


【解决方案1】:

您可能会出现这种行为,因为它们传递变量 $start 和 $end 的方式。在当前情况下,查询正在数据库中查找字符串,但 ID 很可能是一个整数。这可能解释了这种行为。

如果是我假设的,那么将这两个变量转换为:

$start = (int)$_GET['pos1'];
$end = (int)$_GET['pos2'];

然后把sql改成:

"SELECT * FROM preliminary_tests WHERE ID BETWEEN   $start AND $end"

【讨论】:

  • ID 确实是 int,尝试这个并不能解决大问题,但是 ty
【解决方案2】:

在超过 200 个用户名之后,响应变得太大,并且在发送到节点时被分成多个块。看起来您正在解析到达时的每个块,但可能是该块过早地切断了 JSON,这就是您收到错误的原因。您应该能够在到达响应的“数据”事件时附加每个块,并在响应的“结束”事件中解析它们。

这看起来像:

// Set up the request
var post_req = http.request(post_options, function (res) {
    // create an enclosure for usernames 
    // so it's in scope in both callbacks,
    // and instantiate it as an empty string:
    var usernames = "";  

     // append each chunk on arrival:
    res.on('data', function (chunk) {
        usernames += chunk;
    });

    // at the end of the response, parse the full set of chunks:
    res.on('end', function() {
        usernames = JSON.parse(usernames);
        // do something with the parsed usernames
    });
});
post_req.end(); 

看看 MDN 或 CodeSchool 上的闭包,因为当您想在回调之间共享范围时,它们是一个有用的工具。

此外,请查看 Node 的关于 HTTP 响应的“块”和“结束”事件的文档,以了解更多使用它们的方法。


更新:这是一个很棒的explanation on closures SO。

【讨论】:

  • 谢谢!!!!对不起,我不得不问几次,我只是通过我目前正在做的这个项目学习了javascript
  • 不客气!完全没问题 - 这是一个很好的问题。享受学习 JavaScript!
猜你喜欢
  • 2016-12-17
  • 1970-01-01
  • 2018-11-19
  • 2020-02-29
  • 2015-07-13
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多