req.body vazio nas postagens

256

De repente, isso vem acontecendo em todos os meus projetos.

Sempre que eu faço uma postagem no nodejs usando express e body-parser, req.bodyé um objeto vazio.

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

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())

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

app.listen(2000);

app.post("/", function (req, res) {
  console.log(req.body) // populated!
  res.send(200, req.body);
});

Via ajax e carteiro, está sempre vazio.

No entanto, via curl

$ curl -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:2000/

funciona como pretendido.

Tentei configurar manualmente Content-type : application/jsonno primeiro, mas sempre obtive400 bad request

Isso está me deixando louco.

Eu pensei que era algo atualizado no analisador de corpo, mas fiz o downgrade e não ajudou.

Qualquer ajuda apreciada, obrigado.

Joseph Dailey
fonte
16
Então você tentou explicitamente definir o Content-Typecarteiro? Caso contrário, você pode tentar isso, pois já tive problemas antes com o carteiro não enviando um Content-Type.
Mscdex
sim eu fiz. que é quando eu recebi 400: JSON inválida
Joseph Dailey
@mscdex - graças eu não definir conteúdo de tupe no carteiro e estava ficando louco :)
Muzafar Ali
Para as pessoas que estão vindo para cá porque desejam enviar / fazer upload de arquivos de suas APIs e, portanto, precisam usar dados de formulário. Você precisa de algo para lidar com os dados do formulário: npmjs.com/package/multer é um pacote bastante popular.
precisa saber é
Não importa o que aconteça, o carteiro não lida com números inteiros e valores flutuantes muito bem. Se você tem valores inteiros ou flutuador, garantir a aspas duplas tudo, ambas as chaves e valores
anabeto93

Respostas:

272

No Postman, das 3 opções disponíveis para o tipo de conteúdo, selecione "X-www-form-urlencoded" e deve funcionar.

Também para se livrar da mensagem de erro, substitua:

app.use(bodyParser.urlencoded())

Com:

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

Consulte https://github.com/expressjs/body-parser

O middleware 'body-parser' manipula apenas JSON e dados codificados por url, não multipartes

Mick Cullen
fonte
Isso funcionou para o carteiro, não sei por que funciona com o ajax, pois não mudei nada.
Joseph Dailey
Por algum motivo, as postagens http via Angular não precisavam ser codificadas por URL, mas as chamadas ajax. Alguém sabe o porquê?
youngrrrr
Isso funcionou para mim, por que não estava trabalhando com codificação bruta?
Daniel Kobe
9
agora corpo-analisador é embutido com express.js apenas usarapp.use(express.json());
Sujeet Agrahari
Muito obrigado! Apesar do longo tempo em que isso foi respondido, ainda é relevante.
Spray'n'Pray
218

Com o Postman, para testar ações de postagem HTTP com uma carga de dados JSON bruta, selecione a rawopção e defina os seguintes parâmetros de cabeçalho:

Content-Type: application/json

Além disso, certifique-se de agrupar todas as cadeias usadas como chaves / valores em sua carga JSON entre aspas duplas.

O body-parserpacote analisará as cargas úteis JSON brutas de várias linhas.

{
    "foo": "bar"
}

Testado no Chrome v37 e v41 com a extensão Postman v0.8.4.13 ( body-parserv1.12.2 e expressv4.12.3) com a configuração abaixo:

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

// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// ... Your routes and methods here

Postman raw json payload

sirthud
fonte
Oh cara, como eu senti falta de colar um objeto JS literal em vez de um objeto JSON formatado corretamente ...: -S ... obrigado, amigo!
27415 Wes Wes Johnson
Envolvendo todas as seqüências de caracteres usadas como chave / valores entre aspas duplas ... Fácil de perder, mas, de outra forma, um negócio total! Obrigado.
Loxyboi
Bom uso de capturas de tela.
Xan-Kun Clark-Davis
Quando uso form-datano Postman para postar os dados, eu sempre recebo {}o req.body. Devo definir a Content-Typeopção?
Mingchau
56

Cometi um erro muito idiota e esqueci de definir name atributos para entradas no meu arquivo html.

Então, ao invés de

<input type="password" class="form-control" id="password">

Eu tenho isto.

<input type="password" class="form-control" id="password" name="password">

Agora request.bodyé preenchido assim:{ password: 'hhiiii' }

Jason Kim
fonte
1
Bam. Esse foi o problema. Obrigado!
Matt West
Esse era exatamente o meu problema, uma entrada de formulário sem valores de nome, passava horas tentando descobrir isso. Obrigado.
karensantana
37

Eu descobri que funciona ao enviar com o tipo de conteúdo

"application / json"

em combinação com o lado do servidor

app.use(bodyParser.json());

Agora eu posso enviar via

var data = {name:"John"}
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.send(data);

e o resultado está disponível no request.body.nameservidor.

Xan-Kun Clark-Davis
fonte
Obrigado pelo voto positivo. Realmente acho que essa é a solução mais limpa, embora não a mais simples, pois você deve enviar o tipo de conteúdo correto de qualquer maneira. Eu acho que.
Xan-Kun Clark-Davis
esta é a resposta!
Gel
No meu caso, tive que mudar paraxmlHttp.send(JSON.stringify(data));
endo64 11/12/19
18

Encontrei esse problema hoje, e o que foi corrigido foi remover o cabeçalho do tipo de conteúdo no Postman! Muito estranho. Adicioná-lo aqui, caso ajude alguém.

Eu estava seguindo o tutorial do BeerLocker aqui: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

pedra
fonte
2
Eu tive o mesmo problema. tendo o cabeçalho "desmarcado" (e acinzentado) não era suficiente, tive que removê-lo completamente. mesmo que o botão de origem "</>" mostre que eu não estava enviando esse cabeçalho com o Tipo de conteúdo no estado desmarcado, ele ainda precisava ser completamente removido.
theRemix
Não consigo descobrir como remover os cabeçalhos padrão na extensão chrome postman ... talvez você esteja usando o aplicativo?
WestleyArgentum
Ah, eu instalei o aplicativo e ele funciona muito melhor do que a extensão. Desculpe pelo barulho.
WestleyArgentum
12

Você deve verificar se o middleware body-parser está definido corretamente para o tipo de solicitação (json, codificado por url).

Se você configurou,

app.use(bodyParser.json());

então, no carteiro, você deve enviar os dados como não processados.

https://i.stack.imgur.com/k9IdQ.png captura de tela do carteiro

Se você configurou,

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

a opção 'x-www-form-urlencoded' deve ser selecionada.

Tuan
fonte
que tal ter os dois? (bodyParser.urlencoded e bodyParser.json ()) ... qual deles posso usar no carteiro?
TommyLeong 11/03
9

Meu problema era que eu estava criando a rota primeiro

// ...
router.get('/post/data', myController.postHandler);
// ...

e registrando o middleware após a rota

app.use(bodyParser.json());
//etc

devido à estrutura do aplicativo, copiar e colar o projeto a partir de exemplos.

Depois de corrigir o pedido de registro do middleware antes da rota, tudo funcionou.

decreto
fonte
graças fiat, com a ordem certa e usando a guia cru ele trabalhou para mim no passado
Alex
4

Mesmo quando eu estava aprendendo o node.js pela primeira vez em que comecei a aprendê-lo pelo aplicativo da web, eu estava fazendo tudo isso de maneira adequada no meu formulário, ainda não consegui receber valores em uma solicitação posterior. Após uma longa depuração, vim a saber que, no formulário que forneço enctype="multipart/form-data"devido ao qual não consegui obter valores. Eu simplesmente o removi e funcionou para mim.

Shaggie
fonte
sim, isso também trabalhou para obter o corpo forma , mas , em seguida, causou outro problema com a minha forma - basicamente o arquivo não pôde ser carregado, pois isso requerenctype="multipart/form-data"
tsando
btw, apenas para acrescentar ao meu comentário acima, eu consegui começar este trabalho com multer- ver documentação sobre npmjs.com/package/multer
tsando
3

Parece que se você não usar nenhum encType (o padrão é application/x-www-form-urlencoded), receberá campos de entrada de texto, mas não obterá o arquivo.

Se você possui um formulário no qual deseja postar entrada e arquivo de texto, use o multipart/form-datatipo de codificação e, além disso, use o multermiddleware. Multer analisará o objeto de solicitação e se preparará req.filepara você e todos os outros campos de entrada estarão disponíveis req.body.

Mohammad Haque
fonte
1
obrigado - multerfoi realmente a solução para o meu problema. Seria bom se você pudesse adicionar um exemplo de como usar isso como parte de sua resposta
tsando
2

Um problema semelhante aconteceu comigo, simplesmente misturei a ordem dos parâmetros de retorno de chamada. Verifique se você está configurando as funções de retorno de chamada na ordem correta. Pelo menos para quem tem o mesmo problema.

router.post('/', function(req, res){});
Henry Ollarves
fonte
2

Verifique se ["key": "type", "value": "json"] e ["key": "Content-Type", "value": "application / x-www-form-urlencoded"] estão no seu cabeçalhos de solicitação de carteiro

vpage
fonte
2

Resolvi isso usando multero sugerido acima, mas eles deixaram de dar um exemplo de trabalho completo sobre como fazer isso. Basicamente, isso pode acontecer quando você tem um grupo de formulários enctype="multipart/form-data". Aqui está o HTML para o formulário que eu tinha:

<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file">
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
    <input type="submit" value="Get me the stats!" class="btn btn-default">            
  </div>
</form>

E aqui está como usar multerpara obter os valores e nomes deste formulário com Express.jse node.js:

var multer  = require('multer')
var upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
   // req.file is the name of your file in the form above, here 'uploaded_file'
   // req.body will hold the text fields, if there were any 
   console.log(req.file, req.body)
});
tsando
fonte
1

Eu tive o mesmo problema alguns minutos atrás, tentei todo o possível nas respostas acima, mas qualquer uma delas funcionou.

A única coisa que fiz foi atualizar a versão do Node JS, não sabia que a atualização poderia afetar alguma coisa, mas foi.

Instalei a versão JS do nó 10.15.0( versão mais recente), retornei 8.11.3e tudo está funcionando agora. Talvez o body-parsermódulo deva resolver isso.

Phi
fonte
1

Eu não tinha o nome na minha entrada ... meu pedido estava vazio ... feliz que tenha terminado e eu possa continuar codificando. Obrigado a todos!

Resposta que usei por Jason Kim:

Então, ao invés de

<input type="password" class="form-control" id="password">

eu tenho isto

<input type="password" class="form-control" id="password" name="password">
Luke McCormick
fonte
1

você não deve JSON.stringify(data)enviar o AJAX como abaixo.

Este não é o código correto:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: JSON.stringify(data),
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}   

O código correto é:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}
Achilles Ram Nakirekanti
fonte
Uma coisa importante a ser observada aqui é que, no tipo, certifique-se de colocar "POST" em maiúscula. Já vi casos em que o simples uso de "post" levou ao req.body em branco.
Matt C.
1

Se você estiver trabalhando com o carteiro, confirme essas coisas ao solicitar a API

insira a descrição da imagem aqui

vignesh
fonte
0

Eu estava usando restify em vez de express e encontrei o mesmo problema. A solução foi fazer:

server.use(restify.bodyParser());
Prabhat
fonte
0

Eu acredito que isso pode resolver app.use(express.json());

Cleber Carvalho
fonte
0

Altere app.use(bodyParser.urlencoded());seu código para

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

e no carteiro, no cabeçalho, altere o Content-Typevalor de application/x-www-form-urlencodedparaapplication/json

Ta :-)

Abhijith Brumal
fonte
0

Obrigado a todos pelas ótimas respostas! Passei bastante tempo procurando uma solução e, do meu lado, estava cometendo um erro elementar: estava ligando bodyParser.json()de dentro da função:

app.use(['/password'], async (req, res, next) => {
  bodyParser.json()
  /.../
  next()
})

Eu só precisava fazer app.use(['/password'], bodyParser.json())e funcionou ...

musiquarc
fonte
0

No carteiro, mesmo depois de seguir a resposta aceita, eu estava recebendo um corpo de solicitação vazio. O problema acabou por não passar um cabeçalho chamado

Content-Length : <calculated when request is sent>

Esse cabeçalho estava presente por padrão (junto com outros 5) que eu desabilitei. Habilite isso e você receberá o corpo da solicitação.

kaushalpranav
fonte
0

Meu problema foi criar a rota primeiro require("./routes/routes")(app); , mudei para o final do código antes app.listen e funcionou!

Tushar Kudal
fonte