Node.js: Módulo HTTP

Última atualização: 2026-08-26

Bob precisava validar rapidamente uma ideia de API, mas não queria configurar um projeto Express completo; por isso, usou o módulo HTTP nativo para colocar um servidor de API em funcionamento com apenas 20 linhas de código. Desde o tratamento dos métodos de solicitação e a análise de caminhos de URL até o retorno de dados JSON e a definição de códigos de status, Bob percebeu que, depois de compreender os princípios subjacentes, usar uma estrutura de trabalho se tornou, na verdade, muito mais fácil.

1. O que você vai aprender



2. Criando seu primeiro servidor HTTP

http.createServer Aceita uma função de callback que é acionada sempre que uma solicitação é recebida. A função de callback recebe dois parâmetros: request (o objeto da solicitação) e response (o objeto da resposta). server.listen especifica a porta de escuta.

▶ Exemplo: Minimizando um servidor HTTP

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  res.end('Hello, World!');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});
▶ Experimente
BASH
node server.js
TEXT 📖 Somente leitura
Server running at http://localhost:3000/

Basta acessar http://localhost:3000/ no seu navegador para visualizar Hello, World!.



3. O ciclo de vida da solicitação e resposta HTTP

Toda interação HTTP segue o processo de Solicitação → Roteamento → Processamento → Resposta; compreender esse ciclo de vida é a base para a criação de serviços web.

100%
flowchart LR
    A["Client"] -->|"Send Request"| B["request Object<br/>method / url / headers"]
    B --> C["Routing Resolution<br/>pathname + searchParams"]
    C --> D{"Request Method?"}
    D -->|GET| E["Read Query Parameters"]
    D -->|POST / PUT| F["Collect the request body"]
    E --> G["Business Processing"]
    F --> G
    G --> H["response Object<br/>statusCode / headers / body"]
    H -->|"Return Response"| A


4. Propriedades principais do objeto request

request O objeto contém todas as informações da solicitação enviadas pelo cliente; as três propriedades mais utilizadas são method, url e headers.

Propriedade / Método Tipo Descrição Exemplo de valor
req.method string Método da solicitação 'GET', 'POST'
req.url string Caminho da solicitação (incluindo a string de consulta) '/api/users?id=1'
req.headers objeto Objeto de cabeçalho da solicitação { 'content-type': 'application/json' }
req.httpVersion string versão do protocolo HTTP '1.1'
req.socket objeto objeto de soquete subjacente

▶ Exemplo: Informações sobre solicitações de impressão

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  console.log(`Method: ${req.method}`);
  console.log(`URL: ${req.url}`);
  console.log(`Content-Type: ${req.headers['content-type'] || 'N/A'}`);
  res.end('Check your terminal for request info.');
});

server.listen(3000);
▶ Experimente

Envie uma solicitação de teste usando o curl:

BASH
curl -X POST http://localhost:3000/api/data -H "Content-Type: application/json"
TEXT 📖 Somente leitura
Method: POST
URL: /api/data
Content-Type: application/json


5. Métodos principais do objeto response

response Este objeto é usado para enviar dados de resposta ao cliente, incluindo o código de status, os cabeçalhos de resposta e o corpo da resposta.

Método / Propriedade Descrição Exemplo
res.writeHead(statusCode, headers) Como gravar códigos de status e vários cabeçalhos de resposta em uma única operação res.writeHead(200, { 'Content-Type': 'text/plain' })
res.statusCode = n Definir código de status individualmente res.statusCode = 404
res.setHeader(name, value) Definir um único cabeçalho de resposta res.setHeader('Content-Type', 'application/json')
res.write(data) Gravar os dados do corpo da resposta (pode ser chamado várias vezes) res.write('partial')
res.end(data) Enviar o corpo da resposta e encerrar a resposta res.end('done')
res.writeHead Após ser chamado, em seguida res.end() Enviar dados armazenados no buffer

▶ Exemplo: Retornar uma resposta JSON

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const data = { message: 'Success', timestamp: Date.now() };

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(data));
});

server.listen(3000);
▶ Experimente
BASH
curl http://localhost:3000/
TEXT 📖 Somente leitura
{"message":"Success","timestamp":1719792000000}


6. Resolução de roteamento de URLs

req.url contém o caminho completo da solicitação e a string de consulta. O uso de new URL() facilita a separação entre o nome do caminho e os parâmetros de consulta, permitindo o roteamento baseado em caminho.

▶ Exemplo: Roteamento baseado em caminho

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const pathname = url.pathname;

  res.writeHead(200, { 'Content-Type': 'text/plain' });

  if (pathname === '/') {
    res.end('Home Page');
  } else if (pathname === '/about') {
    res.end('About Page');
  } else if (pathname === '/api/status') {
    res.end('OK');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(3000);
▶ Experimente

7. Solicitações GET e parâmetros de consulta

Os parâmetros de uma solicitação GET estão incluídos na string de consulta da URL, e é possível recuperar os pares chave-valor diretamente usando url.searchParams.

▶ Exemplo: Análise de parâmetros de consulta

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method !== 'GET') {
    res.writeHead(405, { 'Content-Type': 'text/plain' });
    res.end('Method Not Allowed');
    return;
  }

  const url = new URL(req.url, `http://${req.headers.host}`);
  const name = url.searchParams.get('name') || 'Guest';
  const page = url.searchParams.get('page') || '1';

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ name, page }));
});

server.listen(3000);
▶ Experimente
BASH
curl "http://localhost:3000/?name=Bob&page=3"
TEXT 📖 Somente leitura
{"name":"Bob","page":"3"}

Observação: searchParams.get() sempre retorna uma string; portanto, é necessário convertê-la manualmente em um número ou outro tipo.



8. Solicitações POST e coleta do corpo da solicitação

Os dados das solicitações POST são transmitidos por meio do corpo da solicitação. O objeto request é um fluxo legível; é necessário monitorar o evento data para coletar blocos de dados e monitorar o evento end para processar os dados completos.

▶ Exemplo: Como coletar o corpo da solicitação POST

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.url === '/api/users') {
    let body = '';

    req.on('data', (chunk) => {
      body += chunk.toString();
    });

    req.on('end', () => {
      try {
        const data = JSON.parse(body);
        res.writeHead(201, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ id: 1, ...data }));
      } catch (e) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
      }
    });
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(3000);
▶ Experimente
BASH
curl -X POST http://localhost:3000/api/users -H "Content-Type: application/json" -d "{\"name\":\"Bob\",\"age\":30}"
TEXT 📖 Somente leitura
{"id":1,"name":"Bob","age":30}


9. Tipo de conteúdo e cabeçalhos de resposta

Content-Type Este é um dos cabeçalhos de resposta mais importantes na comunicação HTTP, pois especifica o formato dos dados do corpo da resposta para o cliente. Se for configurado incorretamente, o cliente não conseguirá analisar os dados corretamente.

Tipo de conteúdo Finalidade Descrição
text/plain Texto simples O tipo de texto mais básico, sem formatação
text/html Página HTML O navegador exibe isso como uma página da web
application/json Dados JSON O formato de resposta mais utilizado em APIs
application/x-www-form-urlencoded Dados do formulário Formato padrão de envio do formulário
multipart/form-data Envio de arquivos Envio de formulário com arquivos
application/xml Dados XML API SOAP ou interface legada
text/css Folha de estilo CSS Folha de estilo
application/octet-stream Fluxo binário Cenários de download de arquivos

▶ Exemplo: O efeito de diferentes tipos de conteúdo para os mesmos dados

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);

  if (url.pathname === '/plain') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('<h1>This is plain text</h1>');
  } else if (url.pathname === '/html') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>This is HTML</h1>');
  } else if (url.pathname === '/json') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'This is JSON' }));
  }
});

server.listen(3000);
▶ Experimente

Quando você acessa /plain, o navegador exibe a aba do código-fonte; quando você acessa /html, o navegador exibe o título principal; e quando você acessa /json, o navegador exibe dados JSON.



10. Referência rápida aos códigos de status HTTP

Um código de status é uma representação padronizada da resposta do servidor a uma solicitação; o cliente determina sua próxima ação com base nesse código de status.

Código de status Categoria Significado Situações comuns
200 2xx Sucesso OK A solicitação GET retornou dados com sucesso
201 2xx Sucesso Criado Recurso POST criado com sucesso
204 2xx Sucesso Sem conteúdo Exclusão bem-sucedida, nenhum conteúdo retornado
301 Redirecionamento 3xx Movido permanentemente Redirecionamento permanente para o novo URL
302 Redirecionamento 3xx Encontrado Redirecionamento temporário
304 Redirecionamento 3xx Não modificado Acertou no cache; não é necessário retransmitir
400 Erro do cliente 4xx Solicitação inválida Formato inválido do parâmetro da solicitação
401 Erro 4xx do cliente Não autorizado Não autenticado; é necessário fazer login
403 Erro 4xx do cliente Acesso proibido Autenticado, mas sem permissões
404 Erro 4xx do cliente Não encontrado A rota ou o recurso não existe
405 Erro do cliente 4xx Método não permitido O método da solicitação não é permitido
500 Erro 5xx do servidor Erro interno do servidor Erro interno do servidor
502 Erro 5xx do servidor Gateway inválido O gateway/proxy recebeu uma resposta inválida
503 Erro 5xx do servidor Serviço indisponível Serviço temporariamente indisponível

▶ Exemplo: Retornando códigos de status diferentes com base em condições

JAVASCRIPT
const http = require('http');

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const id = url.searchParams.get('id');

  if (!id) {
    res.writeHead(400, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Missing id parameter' }));
  } else if (id === '0') {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'User not found' }));
  } else {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ id, name: 'Bob' }));
  }
});

server.listen(3000);
▶ Experimente

11. Exemplo abrangente: um servidor de API REST simples

Combine todos os conceitos abordados até agora para criar um servidor de API REST que suporte rotas GET/POST, respostas em JSON e análise de parâmetros de consulta. Mantenha uma lista de usuários na memória e ofereça suporte a três operações: consultar todos os usuários, consultar um único usuário e criar um usuário.

JAVASCRIPT
const http = require('http');

const users = [
  { id: 1, name: 'Bob', email: 'bob@example.com' },
  { id: 2, name: 'Alice', email: 'alice@example.com' },
];
let nextId = 3;

function parseBody(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', (chunk) => { body += chunk.toString(); });
    req.on('end', () => {
      try { resolve(JSON.parse(body)); }
      catch (e) { reject(e); }
    });
    req.on('error', reject);
  });
}

function sendJSON(res, statusCode, data) {
  res.writeHead(statusCode, {
    'Content-Type': 'application/json',
    'X-Powered-By': 'Node.js',
  });
  res.end(JSON.stringify(data));
}

const server = http.createServer(async (req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const pathname = url.pathname;

  // GET /api/users
  if (req.method === 'GET' && pathname === '/api/users') {
    const limit = parseInt(url.searchParams.get('limit')) || 10;
    sendJSON(res, 200, users.slice(0, limit));
    return;
  }

  // GET /api/users/:id
  if (req.method === 'GET' && pathname.startsWith('/api/users/')) {
    const id = parseInt(pathname.split('/').pop());
    const user = users.find((u) => u.id === id);
    if (!user) {
      sendJSON(res, 404, { error: 'User not found' });
    } else {
      sendJSON(res, 200, user);
    }
    return;
  }

  // POST /api/users
  if (req.method === 'POST' && pathname === '/api/users') {
    try {
      const data = await parseBody(req);
      if (!data.name || !data.email) {
        sendJSON(res, 400, { error: 'name and email are required' });
        return;
      }
      const newUser = { id: nextId++, name: data.name, email: data.email };
      users.push(newUser);
      sendJSON(res, 201, newUser);
    } catch (e) {
      sendJSON(res, 400, { error: 'Invalid JSON body' });
    }
    return;
  }

  // 404 fallback
  sendJSON(res, 404, { error: 'Route not found' });
});

server.listen(3000, () => {
  console.log('REST API server running at http://localhost:3000/');
});

Teste todas as interfaces:

BASH
# Query All Users
curl http://localhost:3000/api/users

# Query a Single User
curl http://localhost:3000/api/users/1

# Create a New User
curl -X POST http://localhost:3000/api/users -H "Content-Type: application/json" -d "{\"name\":\"Charlie\",\"email\":\"charlie@example.com\"}"

# Accessing a Route That Does Not Exist
curl http://localhost:3000/unknown
TEXT 📖 Somente leitura
[{"id":1,"name":"Bob","email":"bob@example.com"},{"id":2,"name":"Alice","email":"alice@example.com"}]

{"id":1,"name":"Bob","email":"bob@example.com"}

{"id":3,"name":"Charlie","email":"charlie@example.com"}

{"error":"Route not found"}

❓ Perguntas Frequentes

P: Qual é a diferença entre o módulo http e o Express? R: O http é um módulo embutido de baixo nível do Node.js que oferece apenas o gerenciamento mais básico de solicitações e respostas; o Express é uma estrutura construída sobre o módulo http que inclui recursos avançados, como roteamento, middleware e um mecanismo de modelos, proporcionando maior eficiência no desenvolvimento, mas introduzindo dependências adicionais.

P: Como faço para recuperar o corpo de uma solicitação POST? R: O objeto req é um fluxo legível. Você precisa aguardar o evento data para coletar os blocos do buffer e concatená-los; em seguida, aguardar o evento end para indicar que a recepção dos dados está concluída e, por fim, usar JSON.parse() ou Buffer.concat() para processar os dados completos.

P: Qual é a diferença entre res.end() e res.write()? R: res.end() Envia dados e fecha a resposta; deve ser chamado uma vez — e apenas uma vez — para cada solicitação; res.write() apenas grava os dados, mas não fecha a resposta; pode ser chamado várias vezes para transmissão contínua ou em blocos, mas res.end() ainda deve ser chamado no final para fechar a resposta.

P: Por que é necessário definir o Content-Type ao retornar JSON? R: Se o Content-Type não for definido, o padrão é text/plain. Os clientes (navegadores, fetch, curl) não analisarão automaticamente a resposta como JSON, o que pode resultar em erros response.json() ou na exibição incorreta dos dados. Definir o parâmetro como application/json garante que os clientes saibam como analisar o corpo da resposta.

P: Como faço para lidar com parâmetros de consulta em uma URL? R: Use new URL(req.url, 'http://localhost') para criar um objeto URL; em seguida, use url.searchParams.get('key') para recuperar os valores dos parâmetros ou use url.searchParams.entries() para percorrer todos os parâmetros.

P: Qual é a finalidade do segundo callback para server.listen? R: É um callback que é acionado após o servidor ter sido iniciado com sucesso e costuma ser usado para exibir logs de inicialização. Se você não passar um callback, também pode monitorar o evento server.on('listening', callback), que tem o mesmo efeito.

P: Por que o segundo parâmetro de new URL precisa incluir base? R: req.url contém apenas a parte do caminho (por exemplo, /api?id=1) e não é uma URL completa. new URL() requer um parâmetro base para completar o protocolo e o nome do host; caso contrário, será gerado um TypeError. O valor de base não afeta os resultados da análise de pathname e searchParams.


📖 Resumo


📝 Exercícios

  1. Conclua todos os exemplos de código desta lição e certifique-se de que cada um deles seja executado corretamente.
  2. Modifique o exemplo completo e adicione suas próprias extensões
  3. Analise a documentação oficial, identifique 1 ou 2 APIs que não foram abordadas nesta aula e escreva um código de teste para elas.
  4. Reflexão: Como você aplicaria o que aprendeu nesta aula a um projeto do mundo real?
  5. Tente combinar o que você aprendeu nesta aula com o conteúdo das aulas anteriores para criar um pequeno projeto.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%