Obtendo Dados do Cliente em Node.js
Todos os dados da solicitação são passados através do objeto request
, que é o primeiro parâmetro da função http.createServer()
. No entanto, pode ser desafiador obter os dados enviados pelo cliente a partir deste objeto. Isso ocorre principalmente porque a função de callback em http.createServer()
é chamada ao receber todos os cabeçalhos HTTP, mas não o corpo da solicitação. Além disso, o próprio objeto request
é um fluxo que recebe dados em pedaços separados. Portanto, para obter os dados da solicitação, precisamos escutar esse fluxo e extrair os pedaços de informação recebidos sequencialmente.
Neste caso, podemos usar diferentes métodos para obter os dados.
Processando os Eventos data e end do Objeto request
O primeiro método consiste em escutar o evento data
, onde o manipulador recebe os chunks de informação que chegam. Após a recepção de todos os dados, é acionado o evento end
. Por exemplo, podemos definir o seguinte servidor simples:
const http = require("http");
const fs = require("fs");
http
.createServer((request, response) => {
if (request.url === "/user") {
let data = "";
request.on("data", (chunk) => {
data += chunk;
});
request.on("end", () => {
console.log(data);
response.end("Dados recebidos com sucesso");
});
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Ao acessar o endereço /user
, usamos o método request.on
para configurar uma função de callback para o evento data
. Esta função recebe cada pedaço de dados enviado como o parâmetro chunk
. Neste caso, esperamos que o cliente envie texto
. Na função de callback, adicionamos os dados recebidos à variável
data. Sempre que a aplicação recebe uma nova porção de dados, o manipulador de eventos adiciona esses dados à variável data
.
Quando todos os dados são recebidos, o evento end
é acionado. Na função de callback deste evento, sabemos que todos os dados foram recebidos e podemos realizar as manipulações necessárias. Neste caso, os dados recebidos são simplesmente exibidos no console, e uma mensagem de notificação é enviada ao cliente.
Para testar, podemos definir o seguinte cliente na página index.html
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
sendUser();
async function sendUser() {
const response = await fetch("/user", { method: "POST", body: "Tom Smith" });
const responseText = await response.text();
console.log(responseText);
}
</script>
</body>
</html>
Aqui, o cliente envia uma string ao servidor, que, após recebê-la, a exibirá no console:
C:\app>node server.js Servidor iniciado em http://localhost:3000 Tom Smith
Iterando Sobre o Iterador Assíncrono do request
O segundo método envolve iterar sobre o objeto request
, que também fornece um iterador assíncrono para os dados recebidos:
const http = require("http");
const fs = require("fs");
http
.createServer(async (request, response) => {
if (request.url === "/user") {
const buffers = []; // buffer para os dados recebidos
for await (const chunk of request) {
buffers.push(chunk); // adicionando todos os dados recebidos ao buffer
}
const data = Buffer.concat(buffers).toString();
console.log(data);
response.end("Dados recebidos com sucesso");
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Aqui, primeiramente definimos um buffer para os dados recebidos:
const buffers = [];
Depois, iteramos sobre o objeto request
, recebendo dados e adicionando-os ao buffer buffers
:
for await (const chunk of request) {
buffers.push(chunk);
}
No final, usamos a função Buffer.concat()
para unir todos os dados recebidos e convertê-los em uma string usando o método toString()
:
const data = Buffer.concat(buffers).toString();
Dessa forma, não estamos limitados a receber apenas dados textuais. Por exemplo, podemos receber dados no formato JSON:
const http = require("http");
const fs = require("fs");
http
.createServer(async (request, response) => {
if (request.url === "/user") {
const buffers = []; // buffer para os dados recebidos
for await (const chunk of request) {
buffers.push(chunk); // adicionando todos os dados recebidos ao buffer
}
const user = JSON.parse(Buffer.concat(buffers).toString());
console.log(user.name, "-", user.age);
response.end("Dados recebidos com sucesso");
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Aqui, supomos que o cliente está enviando um objeto JSON ao servidor, contendo as propriedades name
e age
. Usamos a função JSON.parse()
para analisar os dados recebidos e convertê-los no formato JSON.
O código do cliente para teste poderia ser assim:
sendUser();
async function sendUser() {
const response = await fetch("/user", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Tom",
age: 37,
}),
});
const responseText = await response.text();
console.log(responseText);
}
Neste caso, a saída do console será semelhante a:
C:\app>node server.js Servidor iniciado em http://localhost:3000 Tom - 37