Express.js req.body indefinido

291

Eu tenho isso como configuração do meu servidor Express

app.use(app.router); 
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());

Mas ainda assim, quando solicito req.body.somethingnas minhas rotas, recebo algum erro ao apontar isso body is undefined. Aqui está um exemplo de uma rota que usa req.body:

app.post('/admin', function(req, res){
    console.log(req.body.name);
});

Eu li que esse problema é causado pela falta de, app.use(express.bodyParser());mas como você pode ver, eu o chamo antes das rotas.

Qualquer pista?

Masiar
fonte

Respostas:

296

Você deve certificar-se de definir todas as configurações ANTES de definir rotas. Se você fizer isso, poderá continuar usando express.bodyParser().

Um exemplo é o seguinte:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

app.configure(function(){
  app.use(express.bodyParser());
  app.use(app.router);
});

app.listen(port);

app.post("/someRoute", function(req, res) {
  console.log(req.body);
  res.send({ status: 'SUCCESS' });
});
Mark Bonano
fonte
9
Isso funcionou para mim. Nota: Infelizmente, alguns tutoriais por aí têm pessoas (como eu) colocando rotas antes do app.configure (). No meu caso, isso foi na forma de app.get / post etc, e um require () incluindo-os.
bendman
1
Muito obrigado, eu tenho solucionado esse problema o dia inteiro.
jfplataroti
11
a partir do expresso 4, app.use (app.router) é removido. consulte os docs github.com/visionmedia/express/wiki/New-features-in-4.x
Jonathan Ong
15
a partir do express 4, os middlewares como bodyParser não são mais empacotados com o Express e devem ser instalados separadamente. Você pode encontrar mais informações aqui: github.com/senchalabs/connect#middleware .
andrea.rinaldi
2
Obrigado. Esta resposta é mais de 2 anos de idade e ainda mantém ajudar as pessoas com problemas :)
Lorenzo Marcon
275

As versões mais recentes do Express (4.x) separaram o middleware da estrutura principal. Se você precisar de analisador de corpo, precisará instalá-lo separadamente

npm install body-parser --save

e faça isso no seu código

var bodyParser = require('body-parser')
var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
Jay
fonte
2
Atualizei recentemente para expressar 4.x. Inicialmente, quando eu estava tentando registrar req.body Ele estava me mostrando indefinido. Depois de instalar e usar o analisador de corpo, ele está fornecendo os valores req.body esperados. :)
Alok Adhao
Achei isso útil ao tentar descobrir por que minhas solicitações POST não estavam funcionando com o json-server.
freethebees
Salvei meu dia, especialmente a parte 'app.use (bodyParser.json ())'. Obrigado mano! : D
neaGaze 24/09
Essa deve ser a resposta aceita, pois funciona totalmente para o Express 4! Obrigado senhor!
Combine
2
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()) me salvou !!
Pramesh Bajracharya
71

Não. Você precisa usar app.use(express.bodyParser())antes app.use(app.router). De fato, app.use(app.router)deve ser a última coisa que você chama.

danmactough
fonte
Mesmo mover app.use(app.router)sob as .usechamadas não resolve o problema :(.
Masiar 7/12/12
Ok, depois de um pouco de luta, resolvi usando em app.use(require('connect').bodyParser());vez de app.use(express.bodyParser());.
Masiar
sim, a resposta é verdadeira mesmo quando se usa var router=express.Router();
Istiaque Ahmed
1
Ligeiro adendo, você ainda deve chamar o middleware de tratamento de erros após o app.router
craft
ABENÇOE ESTE COMENTÁRIO
Ke Ke
40

Primeiro, verifique se você instalou o módulo npm chamado 'body-parser' chamando:

npm install body-parser --save

Certifique-se de incluir as seguintes linhas antes de chamar rotas

var express = require('express');
var bodyParser = require('body-parser');
var app = express();

app.use(bodyParser.json());
Ankit kaushik
fonte
Se estiver usando express.json, por que importar o analisador de corpo?
SanSolo 27/12/18
38

O Express 4, possui um analisador de corpo incorporado. Não é necessário instalar um analisador de corpo separado. Então abaixo funcionará:

export const app = express();
app.use(express.json());
TechTurtle
fonte
37

O cabeçalho Content-Type no pedido é realmente importante, especialmente quando você publica os dados do curl ou de qualquer outra ferramenta.

Verifique se você está usando algo como application / x-www-form-urlencoded, application / json ou outros, isso depende dos dados da postagem. Deixar este campo em branco confundirá o Express.

Kevin Xue
fonte
12
+1 Este foi o problema para mim. Eu estava usando o Postman for Chrome para testar uma API JSON criada no REST, mas o objeto recebido pelo Express estava vazio todas as vezes. Acontece que o Postman, por padrão, não adiciona automaticamente o cabeçalho 'Content-Type: application / json', mesmo se você selecionar raw> json.
Jordânia
@ Jordan +1 Obrigado por apontar isso. Na verdade, acabei de verificar meus cabeçalhos e vejo que ainda está definido como 'text / plain' mesmo que eu tenha selecionado 'json'.
Engineer
Ugh ... 7 anos depois e isso ainda é o que está me
atrapalhando
33

Como já postado em um comentário, resolvi usando

app.use(require('connect').bodyParser());

ao invés de

app.use(express.bodyParser());

Ainda não sei por que o simples express.bodyParser()não está funcionando ...

Masiar
fonte
1
@ Massiar Isso não está funcionando para mim. Estou usando o expressjs 4 e recebo um erro como este. Erro: Não foi possível encontrar o módulo 'conectar'
Jeyarathnem Jeyachanthuru
1
A mina @JeyTheva é uma solução bastante antiga, portanto as coisas podem ter mudado nesse meio tempo. Eu sugiro que você tente instalar o connectmódulo via npm install connecte tente novamente. Essa é a única coisa em que consigo pensar lendo a saída do seu erro.
Masiar
4
Aqui está a documentação mais recente para resolver esse problema: npmjs.com/package/body-parser Para outras pessoas que enfrentam esse problema "post express 4", o que funcionou para mim foi definir o Content-Typecabeçalho application/json.
Grant Eagon
3
Aqui está a documentação mais recente para resolver esse problema: npmjs.com/package/body-parser Depois de instalar o analisador de corpo, ele ainda não funcionou. O que funcionou foi definir o Content-Typecabeçalho application/jsonquando eu estava fazendo meu pedido.
Grant Eagon
1
application/jsonvs text/jsonna solicitação funciona, conforme sugerido por @GrantEagon.
Strider
21
// Require body-parser (to receive post data from clients)

var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json

app.use(bodyParser.json())
ASHISH RANJAN
fonte
20

Adicione no seu app.js

antes da chamada do roteador

const app = express();
app.use(express.json());
abdesselam
fonte
2
você salvou meu dia, cara! A chave é adicionar a linha antes do roteador de chamada
ubaldisney
Essa coisa me salvou. Obrigado :)
Farrukh Faizy
12

Parece que o analisador de corpo não é mais enviado com express. Talvez seja necessário instalá-lo separadamente.

var express    = require('express')
var bodyParser = require('body-parser')
var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!

Consulte a página git https://github.com/expressjs/body-parser para obter mais informações e exemplos.

Praneesh
fonte
1
Este parece ser o novo formato Express 4.x e funcionou para mim. O express.bodyParser () mencionado em outras respostas não funciona na 4.x.
DustinB 21/11
10

Caso alguém tenha o mesmo problema que eu estava tendo; Estou usando um prefixo de URL como

http://example.com/api/

que foi configurado com o roteador

app.use('/api', router); 

e então eu tive o seguinte

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

O que corrigiu meu problema foi colocar a configuração do bodyparser acima app.use('/api', router);

Final

// setup bodyparser
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
    app.use('/api', router); 
Jeff Beagley
fonte
9

O express.bodyParser () precisa ser informado sobre que tipo de conteúdo é que está analisando. Portanto, você precisa garantir que, ao executar uma solicitação POST, inclua o cabeçalho "Tipo de conteúdo". Caso contrário, bodyParser pode não saber o que fazer com o corpo da sua solicitação POST.

Se você estiver usando curl para executar uma solicitação POST contendo algum objeto JSON no corpo, seria algo parecido com isto:

curl -X POST -H "Content-Type: application/json" -d @your_json_file http://localhost:xxxx/someRoute

Se estiver usando outro método, apenas certifique-se de definir esse campo de cabeçalho usando qualquer convenção apropriada.

ab107
fonte
8

Use app.use (bodyparser.json ()); antes do roteamento. // app.use ("/ api", rotas);

user1614168
fonte
7

Você pode tentar adicionar esta linha de código na parte superior (após as instruções de exigência):

app.use(bodyParser.urlencoded({extended: true}));

Quanto aos motivos pelos quais funciona, confira os documentos: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions

Anthony Cantellano
fonte
Quero dizer, sua resposta está correta, mas não é diferente das outras.
precisa saber é o seguinte
7

Na maioria das vezes, req.body é indefinido devido à falta do analisador JSON

const express = require('express');
app.use(express.json());

pode estar faltando para o analisador de corpo

const bodyParser  = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

e às vezes é indefinido devido à origem das cros, então adicione-as

const cors = require('cors');
app.use(cors())
rei neo
fonte
5

Isso ocorreu comigo hoje. Nenhuma das soluções acima funciona para mim. Mas um pouco de pesquisa no Google me ajudou a resolver esse problema. Estou codificando para o servidor de terceiros.

As coisas ficam um pouco mais complicadas quando o aplicativo node.js requer a leitura de dados POST de streaming, como uma solicitação de um cliente REST. Nesse caso, a propriedade da solicitação "legível" será configurada como true e os dados do POST deverão ser lidos em partes para coletar todo o conteúdo.

http://www.primaryobjects.com/CMS/Article144

spikeyang
fonte
a postagem menciona o envio do formulário HTML como diferente da solicitação do cliente REST. ambos não são solicitação de http? então, o POST é o único caso que requer streaming?
J10 /
5

Perdeu muito tempo:

Dependendo do tipo de conteúdo em sua solicitação de cliente,
o servidor deve ter diferentes, um dos app.use () abaixo:

app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))

Fonte: https://www.npmjs.com/package/body-parser#bodyparsertextoptions

Exemplo:

Para mim, no lado do cliente, eu tinha o cabeçalho abaixo:

Content-Type: "text/xml"

Então, no lado do servidor, eu usei:

app.use(bodyParser.text({type: 'text/xml'}));

Então, req.body funcionou bem.

Manohar Reddy Poreddy
fonte
5

no Express 4, é realmente simples

const app = express()
const p = process.env.PORT || 8082

app.use(express.json()) 
Gerardo Bautista
fonte
4

Para funcionar, você precisa app.use (app.router) após app.use (express.bodyParser ()) , assim:

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);
HenioJR
fonte
1
Seu comentário e trecho de código são contraditórios. Primeiro você diz que tem que usar app.useem app.routerantes express.bodyParser, mas seu código indica claramente que está atrás. Então qual é?
Levi Roberts
1
Me desculpe, cara. Você precisa usar o app.router após o express.bodyParser.
HenriJR
1
Obrigado @LeviRoberts
HenioJR
4
var bodyParser = require('body-parser');
app.use(bodyParser.json());

Isso salvou meu dia.

isdot
fonte
4

Esse problema pode ocorrer porque você não usou o analisador de corpo ( link )

var express = require('express');
var bodyParser  = require('body-parser');

var app = express();
app.use(bodyParser.json());
Arindam
fonte
3

Eu o resolvi com:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});
Kkkk Kkkk
fonte
3

Essa também é uma possibilidade : verifique se você deve escrever esse código antes da rota no arquivo app.js (ou index.js).

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Inamur Rahman
fonte
2

Você pode usar o analisador de corpo expresso.

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
Kuldeep Mishra
fonte
2

A versão mais recente do Express já possui um analisador de corpo incorporado. Então você pode usar:

const express = require('express);
... 
app.use(express.urlencoded({ extended: false }))
.use(express.json());
LEMUEL ADANE
fonte
1

Caso você poste uma mensagem SOAP, precisará usar o analisador de corpo bruto:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

app.use(bodyParser.raw({ type: 'text/xml' }));
opewix
fonte
1

Com base no @ kevin-xue, o tipo de conteúdo precisa ser declarado. Na minha instância, isso estava ocorrendo apenas no IE9 porque o XDomainRequest não define um tipo de conteúdo ; portanto, bodyparser e expressjs estavam ignorando o corpo da solicitação.

Eu resolvi isso definindo o tipo de conteúdo explicitamente antes de passar a solicitação para o analisador de corpo, da seguinte maneira:

app.use(function(req, res, next) {
    // IE9 doesn't set headers for cross-domain ajax requests
    if(typeof(req.headers['content-type']) === 'undefined'){
        req.headers['content-type'] = "application/json; charset=UTF-8";
    }
    next();
})
.use(bodyParser.json());
purpletônico
fonte
1

Os nossos agradecimentos a @spikeyang pela excelente resposta (fornecida abaixo). Depois de ler o artigo sugerido anexado ao post, decidi compartilhar minha solução.

Quando usar?

A solução exigiu que você usasse o roteador expresso para aproveitá-lo .. so: Se você tentou usar a resposta aceita sem sorte, basta copiar e colar esta função:

function bodyParse(req, ready, fail) 
{
    var length = req.header('Content-Length');

    if (!req.readable) return fail('failed to read request');

    if (!length) return fail('request must include a valid `Content-Length` header');

    if (length > 1000) return fail('this request is too big'); // you can replace 1000 with any other value as desired

    var body = ''; // for large payloads - please use an array buffer (see note below)

    req.on('data', function (data) 
    {
        body += data; 
    });

    req.on('end', function () 
    {
        ready(body);
    });
}

e chame assim:

bodyParse(req, function success(body)
{

}, function error(message)
{

});

NOTA: Para cargas úteis grandes - use um buffer de matriz ( mais @ MDN )

ymz
fonte
o pacote bodyParser é comumente usado e converte a carga útil em um objeto de corpo. conforme previsto em outras respostas
Schuere
1

Se você estiver usando alguma ferramenta externa para fazer a solicitação, adicione o cabeçalho:

Content-Type: application/json

Inc33
fonte
Este me ajudou, eu estava trabalhando com o Postman, obrigado amigo.
R.Gurung