
Biblioteca Node.js para streaming de arquivos como respostas HTTP com suporte a conteúdo parcial, requisições condicionais e cabeçalhos de cache configuráveis. Projetada para uso em frameworks web como Fastify.
Send é uma biblioteca para transmitir arquivos do sistema de arquivos como uma resposta HTTP, suportando respostas parciais (Ranges), negociação condicional-GET (If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since), alta cobertura de testes e eventos granulares que podem ser aproveitados para tomar ações apropriadas em sua aplicação ou framework.
Este é um módulo Node.js disponível através do npm registry. A instalação é feita usando o comando npm install:
$ npm install @fastify/send
@types/mime@3 deve ser usado se quiser usar TypeScript; @types/mime@4 removeu os tipos mime.
$ npm install -D @types/mime@3
const send = require('@fastify/send')
Forneça statusCode, headers e stream para o caminho fornecido para enviar a um res. O req é a requisição HTTP do Node.js e o path é um caminho codificado em URL a ser enviado (codificado em URL, não o caminho real do sistema de arquivos).
Habilita ou desabilita a aceitação de requisições com intervalo, o padrão é true. Desabilitar isso não enviará Accept-Ranges e ignorará o conteúdo do cabeçalho da requisição Range.
Habilita ou desabilita a configuração do cabeçalho de resposta Cache-Control, o padrão é true. Desabilitar isso ignorará as opções immutable e maxAge.
Por padrão, esta biblioteca usa o módulo mime para definir o Content-Type da resposta com base na extensão do arquivo solicitado. Para desabilitar essa funcionalidade, defina contentType como false. O cabeçalho Content-Type precisará ser definido manualmente se desabilitado.
Define como os "dotfiles" são tratados quando encontrados. Um dotfile é um arquivo ou diretório que começa com um ponto ("."). Observe que essa verificação é feita no próprio caminho sem verificar se o caminho existe no disco. Se root for especificado, apenas os dotfiles acima da raiz são verificados (ou seja, a própria raiz pode estar dentro de um dotfile quando definido como "deny").
'allow' Nenhum tratamento especial para dotfiles.'deny' Envia um 403 para qualquer requisição de um dotfile.'ignore' Finge que o dotfile não existe e retorna 404.O valor padrão é similar a 'ignore', com a exceção de que esse padrão não ignorará os arquivos dentro de um diretório que começa com um ponto, por compatibilidade reversa.
Deslocamento de byte no qual o fluxo termina, o padrão é o comprimento do arquivo menos 1. O fim é inclusivo no fluxo, significando que end: 3 incluirá o 4º byte no fluxo.
Habilita ou desabilita a geração de etag, o padrão é true.
Se um determinado arquivo não existir, tente anexar uma das extensões fornecidas, na ordem dada. Por padrão, isso está desabilitado (definido como false). Um exemplo de valor que atenderá arquivos HTML sem extensão: ['html', 'htm']. Isso é ignorado se o arquivo solicitado já tiver uma extensão.
Habilita ou desabilita a diretiva immutable no cabeçalho de resposta Cache-Control, o padrão é false. Se definido como true, a opção maxAge também deve ser especificada para habilitar o cache. A diretiva immutable impedirá que clientes compatíveis façam requisições condicionais durante a vida útil da opção maxAge para verificar se o arquivo mudou.
Por padrão, o send suporta arquivos "index.html"; para desabilitar, defina false ou para fornecer um novo índice, passe uma string ou um array na ordem preferida.
Habilita ou desabilita o cabeçalho Last-Modified, o padrão é true. Usa o valor da última modificação do sistema de arquivos.
Forneça um max-age em milissegundos para cache HTTP, o padrão é 0. Isso também pode ser uma string aceita pelo módulo ms.
Especifica o tamanho máximo do conteúdo da resposta, o padrão é o tamanho total do arquivo. Isso será usado quando acceptRanges for true.
Serve arquivos relativos ao path.
Deslocamento de byte no qual o fluxo começa, o padrão é 0. O início é inclusivo, significando que start: 2 incluirá o 3º byte no fluxo.
Quando fornecido, esta opção define o número máximo de bytes que o buffer interno manterá antes de pausar as leituras do recurso subjacente. Se você omitir esta opção (ou passar undefined), o Node.js recorre ao seu padrão interno para fluxos binários legíveis.
A exportação mime é a instância global do mime npm module. Isso é usado para configurar os tipos MIME que estão associados a extensões de arquivo, bem como outras opções para resolver o tipo MIME de um arquivo (como o tipo padrão a ser usado para uma extensão de arquivo desconhecida).
Ele não realiza cache interno; você deve usar um cache de proxy reverso como Varnish para isso, ou aquelas coisas chiques chamadas CDNs. Se sua aplicação é pequena o suficiente para se beneficiar de cache de memória em um único nó, ela é pequena o suficiente para não precisar de cache de forma alguma ;).
Para habilitar a saída de instrumentação debug(), exporte NODE_DEBUG:
$ NODE_DEBUG=send node app
$ npm install
$ npm test
Este exemplo simples enviará um arquivo específico para todas as requisições.
const http = require('node:http')
const send = require('send')
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, '/path/to/index.html')
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
Este exemplo simples servirá todos os arquivos em um diretório fornecido como nível superior. Por exemplo, uma requisição GET /foo.txt enviará de volta /www/public/foo.txt.
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
// Default unknown types to text/plain
send.mime.default_type = 'text/plain'
// Add a custom type
send.mime.define({
'application/x-my-type': ['x-mt', 'x-mtt']
})
const server = http.createServer(function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
Este é um exemplo de servir uma estrutura de diretórios com uma função personalizada para renderizar uma listagem de um diretório.
const http = require('node:http')
const fs = require('node:fs')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
// Transfer arbitrary files from within /www/example.com/public/*
// with a custom handler for directory listing
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream, type, metadata } = await send(req, parseUrl(req).pathname, { index: false, root: '/www/public' })
if(type === 'directory') {
// get directory list
const list = await readdir(metadata.path)
// render an index for the directory
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
res.end(list.join('\n') + '\n')
} else {
res.writeHead(statusCode, headers)
stream.pipe(res)
}
})
server.listen(3000)
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
const server = http.createServer(async function onRequest (req, res) {
// transfer arbitrary files from within
// /www/example.com/public/*
const { statusCode, headers, stream, type, metadata } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
switch (type) {
case 'directory': {
// your custom directory handling logic:
res.writeHead(301, {
'Location': metadata.requestPath + '/'
})
res.end('Redirecting to ' + metadata.requestPath + '/')
break
}
case 'error': {
// your custom error-handling logic:
res.writeHead(metadata.error.status ?? 500, {})
res.end(metadata.error.message)
break
}
default: {
// your custom headers
// serve all files for download
res.setHeader('Content-Disposition', 'attachment')
res.writeHead(statusCode, headers)
stream.pipe(res)
}
}
})
server.listen(3000)
Licenciado sob MIT.