O MIMEType no Node.js ajuda a interpretar, validar e normalizar tipos de mídia como application/json, text/html; charset=utf-8 e multipart/form-data. Em aplicações web, esse dado aparece em requisições, respostas, uploads, APIs, e-mails e integrações entre serviços. Tratar o valor como uma string comum costuma gerar comparações frágeis, bugs com parâmetros e decisões de segurança incorretas.
A classe MIMEType, disponível em node:util, oferece uma representação estruturada com tipo, subtipo, essência e parâmetros. Isso facilita separar text de html, ler charset, normalizar capitalização e serializar o valor novamente de forma consistente.
Neste guia, você aprenderá a usar MIMEType e MIMEParams, validar Content-Type, tratar uploads, negociar respostas, evitar confusão entre extensão e conteúdo real, criar allowlists e testar cenários de segurança.
Importando MIMEType
import { MIMEType } from 'node:util';Em CommonJS:
const { MIMEType } = require('node:util');A documentação oficial está na classe MIMEType do Node.js. A API segue o modelo WHATWG e oferece parsing consistente para tipos de mídia.
Criando uma instância
const mime = new MIMEType('text/html; charset=UTF-8');
console.log(mime.type); // text
console.log(mime.subtype); // html
console.log(mime.essence); // text/html
console.log(mime.params.get('charset')); // UTF-8A propriedade essence contém apenas tipo e subtipo. Ela é útil quando os parâmetros não devem influenciar a decisão principal.
Normalização
const mime = new MIMEType('Application/JSON; Charset=utf-8');
console.log(mime.essence); // application/json
console.log(mime.toString());Comparar strings manualmente falha quando há espaços, capitalização diferente ou parâmetros adicionais. A classe centraliza essa normalização.
Validando Content-Type
function requireJson(contentType) {
if (!contentType) {
throw new Error('Content-Type ausente');
}
const mime = new MIMEType(contentType);
if (mime.essence !== 'application/json') {
throw new Error('Content-Type deve ser application/json');
}
return mime;
}Em uma API, valide o cabeçalho antes de ler e interpretar o corpo. Isso reduz ambiguidade e evita que payloads inesperados cheguem ao parser.
Para estruturar respostas de erro, consulte Problem Details no Node.js.
JSON com sufixo +json
Vários formatos usam subtipos como application/problem+json ou application/merge-patch+json. Uma validação útil pode aceitar o formato principal e sufixos padronizados:
function isJsonMime(value) {
const mime = new MIMEType(value);
return mime.essence === 'application/json' ||
mime.subtype.endsWith('+json');
}Não aceite qualquer subtipo apenas porque termina com json. Use o sufixo estruturado +json e uma allowlist quando a operação exigir um contrato específico.
Parâmetros com MIMEParams
const mime = new MIMEType('text/plain; charset=utf-8; format=flowed');
for (const [name, value] of mime.params) {
console.log(name, value);
}Você também pode alterar parâmetros:
mime.params.set('charset', 'utf-8');
mime.params.delete('format');
console.log(mime.toString());Não use parâmetros arbitrários enviados pelo cliente para tomar decisões sensíveis sem validação.
Charset
Para texto, o charset define como bytes viram caracteres. Mesmo que UTF-8 seja o padrão de muitas APIs modernas, não suponha que todo conteúdo recebido está em UTF-8 quando o protocolo permite outros valores.
function getCharset(contentType) {
const mime = new MIMEType(contentType);
return mime.params.get('charset')?.toLowerCase() ?? null;
}Ao responder JSON, use um cabeçalho claro:
res.setHeader('Content-Type', 'application/json; charset=utf-8');Uploads de arquivos
O Content-Type de um upload é informado pelo cliente e não prova o conteúdo real. Um arquivo executável pode ser enviado como image/png. Use MIMEType para parsing e política inicial, mas valide também assinatura binária, tamanho, extensão permitida e comportamento do arquivo.
Veja Upload Seguro de Arquivos no Node.js e Multipart no Node.js.
Allowlist de tipos
const allowed = new Set([
'image/png',
'image/jpeg',
'application/pdf'
]);
function validateUploadType(value) {
const mime = new MIMEType(value);
if (!allowed.has(mime.essence)) {
throw new Error('Tipo de arquivo não permitido');
}
return mime;
}Prefira allowlist. Bloquear apenas tipos conhecidos como perigosos deixa passar formatos inesperados.
Respostas HTTP
Ao servir arquivos, defina Content-Type explicitamente e adicione proteções contra interpretação indevida:
res.setHeader('Content-Type', mime.toString());
res.setHeader('X-Content-Type-Options', 'nosniff');O cabeçalho nosniff reduz a chance de navegadores tentarem interpretar o conteúdo de forma diferente do tipo declarado.
Negociação com Accept
O cabeçalho Accept pode conter vários valores, pesos e wildcards. MIMEType interpreta um tipo individual, mas não é um parser completo de negociação HTTP. Para Accept complexo, use uma biblioteca confiável ou implemente uma política restrita.
function chooseResponse(accept) {
if (!accept || accept.includes('application/json')) {
return 'application/json';
}
if (accept.includes('text/plain')) {
return 'text/plain';
}
return null;
}Não reutilize diretamente valores de Accept como Content-Type da resposta.
MIME e extensão
Extensão e MIME resolvem problemas diferentes. A extensão ajuda a identificar convenção de nome; o MIME descreve o formato declarado. Nenhum dos dois substitui inspeção real quando segurança importa.
const fileName = 'relatorio.pdf';
const declared = new MIMEType('application/pdf');Uma política robusta compara extensão permitida, MIME declarado e assinatura real.
Content-Type ausente
Em endpoints que exigem corpo estruturado, rejeite o cabeçalho ausente. Em downloads legados, pode ser necessário usar application/octet-stream.
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename="arquivo.bin"');Tratando erros de parsing
function parseMime(value) {
try {
return new MIMEType(value);
} catch {
return null;
}
}Não exponha stack trace ao cliente. Registre o valor de forma limitada e redigida quando ele puder conter dados inesperados.
Integração com fetch
const response = await fetch(url);
const contentType = response.headers.get('content-type');
if (!contentType) {
throw new Error('Resposta sem Content-Type');
}
const mime = new MIMEType(contentType);
if (!isJsonMime(mime.toString())) {
throw new Error(`Formato inesperado: ${mime.essence}`);
}
const data = await response.json();Validar antes de chamar response.json() produz erros melhores e evita tentar interpretar HTML de proxy como JSON.
Veja Fetch no Node.js e Undici no Node.js.
APIs de webhook
Webhooks frequentemente usam application/json, mas alguns provedores enviam application/x-www-form-urlencoded. Valide o tipo antes de selecionar o parser e mantenha a verificação de assinatura sobre os bytes originais quando o protocolo exigir.
Cache e Vary
Quando a resposta muda com base no formato aceito, inclua Vary: Accept para evitar que caches entreguem representação errada.
res.setHeader('Vary', 'Accept');Consulte ETag e Cache HTTP no Node.js.
Testes
import test from 'node:test';
import assert from 'node:assert/strict';
import { MIMEType } from 'node:util';
test('normaliza application/json', () => {
const mime = new MIMEType('Application/JSON; Charset=UTF-8');
assert.equal(mime.essence, 'application/json');
assert.equal(mime.params.get('charset'), 'UTF-8');
});Inclua casos inválidos, parâmetros duplicados, espaços, capitalização, tipos com sufixo e cabeçalhos ausentes.
Erros comuns
- comparar Content-Type por igualdade de string;
- esquecer parâmetros como charset;
- confiar no MIME enviado pelo usuário;
- usar blocklist em vez de allowlist;
- aceitar qualquer subtype terminado em json;
- servir conteúdo sem nosniff;
- usar Accept diretamente na resposta;
- não testar valores malformados.
Checklist
- parse com MIMEType;
- compare pela essence;
- valide parâmetros necessários;
- use allowlist;
- inspecione assinatura de uploads;
- defina Content-Type na resposta;
- adicione nosniff;
- trate erros sem vazar detalhes;
- teste formatos alternativos;
- monitore rejeições.
Conclusão
O MIMEType no Node.js oferece uma forma estruturada de lidar com tipos de mídia. Em vez de manipular cabeçalhos como strings frágeis, a aplicação separa tipo, subtipo, essência e parâmetros de maneira consistente.
Use a classe para validar APIs, interpretar respostas e aplicar políticas de upload, mas lembre que MIME declarado não prova o conteúdo real. Combine parsing, allowlist, inspeção binária e cabeçalhos seguros para obter um fluxo confiável.
Como referência complementar, consulte o registro de tipos de mídia da IANA.




