>  기사  >  백엔드 개발  >  노드 정적 파일 서버에 대한 자세한 설명

노드 정적 파일 서버에 대한 자세한 설명

小云云
小云云원래의
2018-03-09 09:03:541485검색

지원 기능:

  1. 정적 파일 읽기

  2. 디렉토리에 액세스하여 다음 index.html 파일을 자동으로 찾습니다. index.html이 없으면 파일 나열

  3. MIME 유형 지원

  4. 캐시 지원/제어

  5. gzip 압축 지원

  6. 범위 지원, 중단점 재개

  7. 전역 명령 실행

  8. 하위 프로세스 실행

이 글에서는 주로 실용적인 노드 정적 파일을 소개합니다. 서버 예제가 모두에게 도움이 되기를 바랍니다.

1. 정적 파일을 읽는 서비스 만들기

먼저 http 모듈을 소개하고, 서버를 만들고, 구성 포트를 수신합니다.


 const http = require('http');
 
 const server = http.createServer();
 
 // 监听请求
 server.on('request', request.bind(this));
 
 server.listen(config.port, () => {
  console.log(`静态文件服务启动成功, 访问localhost:${config.port}`);
 });

Fn을 작성하여 요청을 구체적으로 처리하고 정적 파일을 반환합니다. , 그리고 url 모듈은 다음 경로를 얻습니다.


 const url = require('url');
 const fs = require('fs');
 function request(req, res) {
 const { pathname } = url.parse(req.url); // 访问路径
 
 const filepath = path.join(config.root, pathname); // 文件路径
 
 fs.createReadStream(filepath).pipe(res); // 读取文件,并响应
 }


 if (pathname === '/') {
  const rootPath = path.join(config.root, 'index.html');
  try{
   const indexStat = fs.statSync(rootPath);
   if (indexStat) {
    filepath = rootPath;
   }
  } catch(e) {
   
  }
 }

2.MIME 유형 지원


mime 모듈을 사용하여 파일 유형을 가져오고 인코딩을 설정하세요.


 fs.stat(filepath, (err, stats) => {
 if (err) {
  res.end('not found');
  return;
 }
 if (stats.isDirectory()) {
  let files = fs.readdirSync(filepath);
  files = files.map(file => ({
   name: file,
   url: path.join(pathname, file)
  }));
  let html = this.list()({
   title: pathname,
   files
  });
  res.setHeader('Content-Type', 'text/html');
  res.end(html);
 }
 }

3. 캐시 지원


http 프로토콜 캐시:

Cache-Control: http1.1 콘텐츠, 고객에게 클라이언트가 데이터를 캐시하는 방법 및 규칙을 알려줍니다


private 클라이언트는 캐시할 수 있습니다


public 클라이언트와 프록시 서버 모두 캐시할 수 있습니다


max- age=60 캐시된 콘텐츠는 60초 후에 만료됩니다.


no-cache는 비교 캐시를 사용하여 데이터를 확인하고 원본 서버에서 강제로 다시 확인해야 합니다.

no-store 모든 콘텐츠가 캐시되지 않습니다. , 강제 캐시나 비교 캐시 모두 트리거되지 않습니다
  1. Expires: http1.0 콘텐츠, 캐시 제어는 캐시가 만료되는 시기를 무시하고 클라이언트에 알려줍니다
  2. ETag: 콘텐츠의 해시 값. 다음에 클라이언트가 요청할 때 요청 헤더에 if-none-match: etag 값을 추가하세요

  3. Last-Modified: 마지막 수정 다음에 클라이언트가 요청할 때 if-modified-since: Last-Modified 값을 추가하세요 요청 헤더

  4.  function list() {
      let tmpl = fs.readFileSync(path.resolve(__dirname, 'template', 'list.html'), 'utf8');
      return handlebars.compile(tmpl);
     }

    4. Compression

  5. 클라이언트가 요청 헤더를 통해 내용을 전달합니다. Accept-Encoding: gzip, deflate 서버는 어떤 압축 형식을 지원합니까? 지원되는 압축 형식. 서버에서 지원하지 않으면 압축이 수행되지 않습니다.

 <!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>{{title}}</title>
 </head>
 <body>
 <h1>hope-server静态文件服务器</h1>
 <ul>
  {{#each files}}
  <li>
   <a href={{url}}>{{name}}</a>
  </li>
  {{/each}}
 </ul>
 </body>
 </html>

5. 재개 가능한 업로드


서버는 요청 헤더의 Range: bytes=0-xxx를 사용하여 Range 요청을 하는지 여부를 확인합니다. 파일 콘텐츠의 해당 부분에 대해 응답 상태 코드는 부분 콘텐츠를 나타내는 206이 되고 Content-Range가 설정됩니다. 유효하지 않은 경우 요청 범위가 만족스럽지 않음을 나타내는 416 상태 코드가 반환됩니다. Range 요청 헤더가 포함되지 않은 경우 계속해서 일반적인 방식으로 응답합니다.


res.setHeader(&#39;Content-Type&#39;, mime.getType(filepath) + &#39;;charset=utf-8&#39;);

6. 전역 명령 실행


npm 링크를 통해 구현됨


npm 패키지 디렉터리에 대한 소프트 링크를 만들고 이를 실행 파일로 {prefix}/lib/node_modules/


에 연결합니다. 파일(bin)은 소프트 링크를 생성하고 이를 {prefix}/bin/{name}


에 연결합니다. npm link 명령은 디렉터리와 실행 파일을 연결하여 npm package 명령을 전역적으로 실행 가능하게 만듭니다.


package.json의 구성


 handleCache(req, res, stats, hash) {
 // 当资源过期时, 客户端发现上一次请求资源,服务器有发送Last-Modified, 则再次请求时带上if-modified-since
 const ifModifiedSince = req.headers[&#39;if-modified-since&#39;];
 // 服务器发送了etag,客户端再次请求时用If-None-Match字段来询问是否过期
 const ifNoneMatch = req.headers[&#39;if-none-match&#39;];
 // http1.1内容 max-age=30 为强行缓存30秒 30秒内再次请求则用缓存 private 仅客户端缓存,代理服务器不可缓存
 res.setHeader(&#39;Cache-Control&#39;, &#39;private,max-age=30&#39;);
 // http1.0内容 作用与Cache-Control一致 告诉客户端什么时间,资源过期 优先级低于Cache-Control
 res.setHeader(&#39;Expires&#39;, new Date(Date.now() + 30 * 1000).toGMTString());
 // 设置ETag 根据内容生成的hash
 res.setHeader(&#39;ETag&#39;, hash);
 // 设置Last-Modified 文件最后修改时间
 const lastModified = stats.ctime.toGMTString();
 res.setHeader(&#39;Last-Modified&#39;, lastModified);
 
 // 判断ETag是否过期
 if (ifNoneMatch && ifNoneMatch != hash) {
  return false;
 }
 // 判断文件最后修改时间
 if (ifModifiedSince && ifModifiedSince != lastModified) {
  return false;
 }
 // 如果存在且相等,走缓存304
 if (ifNoneMatch || ifModifiedSince) {
  res.writeHead(304);
  res.end();
  return true;
 } else {
  return false;
 }
 }
    프로젝트 아래에 bin 디렉터리 희망 파일을 생성하고 yargs 구성 명령줄을 사용하여 매개변수 전달
  1.  getEncoding(req, res) {
      const acceptEncoding = req.headers[&#39;accept-encoding&#39;];
      // gzip和deflate压缩
      if (/\bgzip\b/.test(acceptEncoding)) {
       res.setHeader(&#39;Content-Encoding&#39;, &#39;gzip&#39;);
       return zlib.createGzip();
      } else if (/\bdeflate\b/.test(acceptEncoding)) {
       res.setHeader(&#39;Content-Encoding&#39;, &#39;deflate&#39;);
       return zlib.createDeflate();
      } else {
       return null;
      }
     }

    7에서 구현한 하위 프로세스입니다. spawn

index.js



 getStream(req, res, filepath, statObj) {
  let start = 0;
  let end = statObj.size - 1;
  const range = req.headers[&#39;range&#39;];
  if (range) {
   res.setHeader(&#39;Accept-Range&#39;, &#39;bytes&#39;);
   res.statusCode = 206;//返回整个内容的一块
   let result = range.match(/bytes=(\d*)-(\d*)/);
   if (result) {
    start = isNaN(result[1]) ? start : parseInt(result[1]);
    end = isNaN(result[2]) ? end : parseInt(result[2]) - 1;
   }
  }
  return fs.createReadStream(filepath, {
   start, end
  });
 }

8. 소스 코드 및 테스트


소스 코드 주소: hope-server


 {
 bin: {
 "hope-server": "bin/hope"
 }
 }

아무 디렉토리나 입력하세요


 // 告诉电脑用node运行我的文件
 #! /usr/bin/env node
 
 const yargs = require(&#39;yargs&#39;);
 const init = require(&#39;../src/index.js&#39;);
 const argv = yargs.option(&#39;d&#39;, {
 alias: &#39;root&#39;,
 demand: &#39;false&#39;,
 type: &#39;string&#39;,
 default: process.cwd(),
 description: &#39;静态文件根目录&#39;
 }).option(&#39;o&#39;, {
 alias: &#39;host&#39;,
 demand: &#39;false&#39;,
 default: &#39;localhost&#39;,
 type: &#39;string&#39;,
 description: &#39;配置监听的主机&#39;
 }).option(&#39;p&#39;, {
 alias: &#39;port&#39;,
 demand: &#39;false&#39;,
 type: &#39;number&#39;,
 default: 8080,
 description: &#39;配置端口号&#39;
 }).option(&#39;c&#39;, {
 alias: &#39;child&#39;,
 demand: &#39;false&#39;,
 type: &#39;boolean&#39;,
 default: false,
 description: &#39;是否子进程运行&#39;
 })
 .usage(&#39;hope-server [options]&#39;)
 .example(
 &#39;hope-server -d / -p 9090 -o localhost&#39;, &#39;在本机的9090端口上监听客户端的请求&#39;
 ).help(&#39;h&#39;).argv;
 
 // 启动服务
 init(argv);

Re 늦은 추천:


nodejs 및 Python으로 작성된 간단한 HTTP 정적 파일 서버 사용


nodejs 및 Python_node.js로 작성된 간단한 HTTP 정적 파일 서버

Node.js 정적 파일 서버 개선된 version_node.js


위 내용은 노드 정적 파일 서버에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.