簡體   English   中英

查詢數據庫 PostgrSQL 后無法 res.send()(錯誤:“將標頭發送到客戶端后無法設置標頭”)

[英]Can not res.send() (error: "Cannot set headers after they are sent to the client") after I do query to database PostgrSQL

我知道,這聽起來很奇怪,但這是真的。 我正坐在 node.js 上制作 API,但是當我開始測試它時,我驚訝地發現幾乎在查詢處理開始時,當第一個 res.status().send() 到達時,VS 代碼掉落了一個“將標頭發送到客戶端后無法設置標頭”錯誤。
我如何意識到數據庫查詢是有罪的? 我使用“res.finished”屬性來檢查它何時“發送給客戶端”,並發現 res.finished 在數據庫查詢之后從“false”變為“true”。

誰知道它會是什么? 我已經用 MySQL 數據庫做了同樣的 API 事情,一切順利,但現在我使用的是 PostgreSQL,所以事情開始發生了。

我從 typescript 文件導出“PostgreSQL 管理器”class

PostgreSQL_Manager.ts:

module.exports = {
    PostgreSQL_db_manager    
}

在 index.ts 中導入並初始化:

index.ts

const PostgreSQL_mngr = require('./PostgreSQL_Manager.ts').PostgreSQL_db_manager;
const db = new PostgreSQL_mngr;

然后,如果我用查詢數據庫注釋語句,res.finished 保持假(我用 readRows (SELECT) 和 createRows(INSERT INTO) 試過):

Piece of index.ts code: 

console.log('res.finished : ', res.finished);
//let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
//await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);

Piece of Terminal:

res.finished :  false
res.finished :  false

但是當我取消注釋數據庫查詢時,它變成了這樣:

Piece of index.ts code: 

console.log('res.finished : ', res.finished);
//let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);

Piece of Terminal:

res.finished :  false
Postgres: Rows were created...
res.finished :  true

postgres 管理器 class 中的 db.createRows 代碼如下所示:

public async createRows(table : string, columns: string | string[], values: string | string[]) : Promise<void> {
        let createPromise = new Promise<void> ((resolve, reject) => {
            this.db.query(`INSERT INTO ${table} ${columns} VALUES ${values};`, (err) => {
                if(err) throw err;
                console.log('Postgres: Rows were created...');
                resolve();
            });
        });
        await createPromise;        
    }

編輯 1:發生錯誤(此 function 從 app.post 調用,昵稱,email 和密碼具有字符串值):

async function validationUsers (res : any, email : string = undefined, password : string = undefined, nickname : string = undefined) : Promise<boolean> {
    console.log('f:validationUsers email : ', email);
    console.log('f:validationUsers password : ', password);
    console.log('f:validationUsers : nickname', nickname);
    //validation: nickname and email
    if(nickname) {
        console.log('res.finished : ', res.finished);
        //let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
        await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
        console.log('res.finished : ', res.finished);
        /* if(nickval[0] !== undefined) {
            console.log('frofkofro');
            res.status(410).send('Nickname already exists');
            res.end();
            return false;
        } */
    }
    //validation: email
    if(email) {
        let emailval : any = await db.readRows('users', 'email', `email = \'${email}\'`);
        console.log('f:validationUsers if(email) emailval[0] : ', emailval[0]);
        if(emailval[0] !== undefined) {
            console.log("?00");
            res.send('Email already exists');
            res.end();
            return false;
        }
    }
    //validation: password
    if(password) {
        let passwordval = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,100}$/;
        if(!password.match(passwordval)) {
            console.log('password BAM!!!');
            res.status(412).send('Password does not match the criteria'); <-- **THIS STRING**
            console.log('password BOOM!!!');
            //res.end();
            return false;
        }
    }
    console.log('End of f:validationUsers');
    return true;
}

編輯 2:從 PostgreSQL 的“pg”庫到數據庫的 pool.query 或池連接是否有問題? 或者可能是 ts-node 編譯器的問題?

所以,我真的不明白這是怎么回事。 我不知道它是否重要,但我使用 ts-node 進行編譯和渲染 typescript

編輯 3:好的,所以我開始使用具有相同 5000 端口的新 ts 文件新服務器並運行以下命令:

app1.get('/db', async (req : any, res : any) => {
  console.log('res.finished : ', res.finished);
  await db1.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
  console.log('res.finished : ', res.finished);
  res.status(200).send('All is fine this is send');
  res.end();
});

並在控制台中產生:

Connected to database as pool successfully...
Server started on port 5000
res.finished :  false
Postgres: Rows were created...
res.finished :  false

而 POSTMAN 收到了 res.send()。 卧槽?????

當您的 PostgreSQL 代碼使用res.send()發送多個結果時,會發生錯誤“標頭已發送...”。

我假設res.send()部分在 PostgreSQL 管理器中,它看起來像一個經過測試的真實庫 - 那么是什么讓它向一個查詢發送兩個答案呢?

我沒有使用 Typescript 和 pSQL 的經驗,但我使用過 pSQL,並且記得幾年前遇到過同樣的問題。

PostgreSQL 支持(我想它仍然支持)多種查詢模式,例如UPDATE b SET a=2 WHERE c; SELECT a FROM b UPDATE b SET a=2 WHERE c; SELECT a FROM b 這是兩個陳述,也是某些漏洞利用甚至可以起作用的原因。

而且,就像它發生在我身上一次,即使第二個長度為零並且顯然甚至不是查詢,在您的代碼中

 `INSERT INTO ${table} ${columns} VALUES ${values};`

您的 PostgreSQL 經理可能只是認為有兩個語句。

所以,嘗試刪除那個看似無害的';' 最后,看看它是否解決了問題。 我沒有使用你的庫,但對我來說,它做到了。

我會說錯誤來自這里:

        res.send('Email already exists');
        res.end();

事實上,如果你節點的文檔是這樣寫的:

res.end() function 用於結束響應過程。 這個方法實際上來自Node核心,具體是HTTP.ServerResponse的response.end()方法。 用於在沒有任何數據的情況下快速結束響應。

鑒於您已經回復了'Email already exists' express.js,您會收到錯誤消息Cannot set headers after they are sent to the client (這只是意味着您已經發送了回復)

我想只是刪除res.end(); 會解決你的問題。

好吧,這真的很奇怪。 我有中間件 function app.use,它看起來像這樣:

app.use(async function (req : any, res : any, next : any) {
   console.log(smthng);
   get('header') stuff;
   if (cond) {
      // this is not executed because condition was false in all my situation
   } else {
      // this is executed in all cases of this thread
      req.name = undefined;
      next();
   }
   next()
})

如您所見,中間件 function 的末尾是 next()。 所以,我刪除了 JUST THIS NEXT AND:


Terminal:

res.finished :  false
Postgres: Rows were read...
[]
res.finished :  false
res.finished :  false
Postgres: Rows were read...
[]
f:validationUsers if(email) emailval[0] :  undefined
res.finished :  false
password BAM!!!
password BOOM!!!

我不知道發生了什么,我認為這是在 db promise、中間件和 res.send() 之間的十字路口下的深海精神分裂症超流體流動

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM