
Node.js 라이브러리로, 부분 콘텐츠, 조건부 요청, 구성 가능한 캐싱 헤더를 지원하며 파일을 HTTP 응답으로 스트리밍합니다. Fastify와 같은 웹 프레임워크에서 사용하도록 설계되었습니다.
Send는 파일 시스템의 파일을 HTTP 응답으로 스트리밍하기 위한 라이브러리로, 부분 응답(Ranges), 조건부 GET 협상(If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since), 높은 테스트 커버리지, 그리고 애플리케이션이나 프레임워크에서 적절한 조치를 취하는 데 활용할 수 있는 세분화된 이벤트를 지원합니다.
이것은 npm 레지스트리를 통해 제공되는 Node.js 모듈입니다. 설치는 npm install 명령을 사용하여 수행합니다:
$ npm install @fastify/send
TypeScript를 사용하려면 @types/mime@3을 사용해야 합니다;
@types/mime@4에서는 mime 타입이 제거되었습니다.
$ npm install -D @types/mime@3
const send = require('@fastify/send')
res로 전송할 주어진 경로에 대한 statusCode, headers, stream을 제공합니다. req는 Node.js HTTP 요청이며, path는 전송할 urlencoded 경로입니다(urlencoded이며 실제 파일 시스템 경로가 아닙니다).
범위 요청 수락을 활성화하거나 비활성화하며, 기본값은 true입니다.
비활성화하면 Accept-Ranges를 전송하지 않고 Range 요청 헤더의 내용을 무시합니다.
Cache-Control 응답 헤더 설정을 활성화하거나 비활성화하며, 기본값은
true입니다. 비활성화하면 immutable 및 maxAge 옵션을 무시합니다.
기본적으로 이 라이브러리는 mime 모듈을 사용하여 요청된 파일의
파일 확장자에 따라 응답의 Content-Type을 설정합니다.
이 기능을 비활성화하려면 contentType을 false로 설정하십시오.
비활성화하면 Content-Type 헤더를 수동으로 설정해야 합니다.
"dotfile"이 발견되었을 때 처리하는 방법을 설정합니다. dotfile은 점(".")으로
시작하는 파일 또는 디렉터리입니다. 이 검사는 경로가 디스크에
존재하는지 확인하지 않고 경로 자체에 대해 수행됩니다. root가 지정된 경우
root 위의 dotfile만 검사됩니다(즉, "deny"로 설정된 경우 root 자체가
dotfile 내에 있을 수 있습니다).
'allow' dotfile에 대한 특별한 처리가 없습니다.'deny' dotfile에 대한 모든 요청에 403을 전송합니다.'ignore' dotfile이 존재하지 않는 것처럼 가장하고 404를 반환합니다.기본값은 'ignore'와 유사 하지만, 하위 호환성을 위해 점으로 시작하는
디렉터리 내의 파일은 무시하지 않는다는 예외가 있습니다.
스트림이 끝나는 바이트 오프셋이며, 기본값은 파일 길이에서
1을 뺀 값입니다. 끝은 스트림에서 포함되므로, end: 3은
스트림의 4번째 바이트를 포함합니다.
etag 생성을 활성화하거나 비활성화하며, 기본값은 true입니다.
주어진 파일이 존재하지 않는 경우, 주어진 순서대로 주어진 확장자 중
하나를 추가해 봅니다. 기본적으로 이 기능은 비활성화되어 있습니다(false로 설정).
확장자가 없는 HTML 파일을 제공하는 예시 값: ['html', 'htm'].
요청된 파일에 이미 확장자가 있는 경우 이 기능은 건너뜁니다.
Cache-Control 응답 헤더의 immutable 지시문을 활성화하거나 비활성화하며,
기본값은 false입니다. true로 설정하면 캐싱을 활성화하기 위해 maxAge 옵션도
지정해야 합니다. immutable 지시문은 지원되는 클라이언트가
maxAge 옵션의 수명 동안 파일이 변경되었는지 확인하기 위해 조건부 요청을
하는 것을 방지합니다.
기본적으로 send는 "index.html" 파일을 지원합니다. 이를 비활성화하려면
false로 설정하거나, 새로운 인덱스를 제공하려면 선호하는 순서로
문자열 또는 배열을 전달하십시오.
Last-Modified 헤더를 활성화하거나 비활성화하며, 기본값은 true입니다. 파일
시스템의 마지막 수정 값을 사용합니다.
HTTP 캐싱을 위한 max-age를 밀리초 단위로 제공하며, 기본값은 0입니다. ms 모듈에서 허용하는 문자열일 수도 있습니다.
최대 응답 콘텐츠 크기를 지정하며, 기본값은 전체 파일 크기입니다.
이는 acceptRanges가 true일 때 사용됩니다.
파일 확인 후, 그러나 응답 처리 및 파일 스트림 생성 전에 최종 선택된 파일의
절대 경로와 파일 시스템 통계와 함께 호출됩니다. 콜백은 동기적이거나
프로미스를 반환할 수 있습니다. 프로미스를 반환하면 send는 그것이
settle될 때까지 기다립니다. 콜백이 예외를 던지거나 반환된 프로미스가
거부되면 작업이 중단되고 send()가 거부됩니다.
path를 기준으로 파일을 제공합니다.
스트림이 시작되는 바이트 오프셋이며, 기본값은 0입니다. 시작은 포함되므로,
start: 2는 스트림의 3번째 바이트를 포함합니다.
제공되면, 이 옵션은 기본 리소스로부터 읽기를 일시 중지하기 전에 내부 버퍼가 보유할 최대 바이트 수를 설정합니다. 이 옵션을 생략하거나(또는 undefined를 전달하면) Node.js는 읽기 가능한 바이너리 스트림에 대한 내장 기본값으로 대체됩니다.
mime export는 mime npm 모듈의 전역 인스턴스입니다.
이는 파일 확장자와 연결된 MIME 타입을 구성하는 데 사용되며, 파일의 MIME 타입을 확인하는 방법에 대한 다른 옵션(예: 알 수 없는 파일 확장자에 사용할 기본 타입)에도 사용됩니다.
내부 캐싱은 수행하지 않으며, 이를 위해서는 Varnish와 같은 리버스 프록시 캐시나 CDN이라고 불리는 멋진 것들을 사용해야 합니다. 애플리케이션이 단일 노드 메모리 캐싱의 이점을 얻을 만큼 충분히 작다면, 캐싱이 전혀 필요하지 않을 만큼 작은 것입니다 ;).
debug() 계측 출력을 활성화하려면 __NODE_DEBUG__를 export하세요:
$ NODE_DEBUG=send node app
$ npm install
$ npm test
이 간단한 예제는 모든 요청에 특정 파일을 전송합니다.
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)
이 간단한 예제는 주어진 디렉터리의 모든 파일을 최상위 수준으로 제공합니다. 예를 들어, GET /foo.txt 요청은 /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)
다음은 디렉터리 목록을 렌더링하는 사용자 정의 함수를 사용하여 디렉터리 구조를 제공하는 예시입니다.
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)
MIT에 따라 라이선스가 부여됩니다.