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

小云云
풀어 주다: 2018-03-12 09:35:00
원래의
1305명이 탐색했습니다.

이 기사에서는 주로 실용적인 노드 정적 파일 서버의 예를 소개합니다. 먼저 해당 기능을 나열한 다음 코드 형식으로 공유하겠습니다.

지원 기능:

  1. 정적 파일 읽기

  2. 아래 디렉토리에 접근하면 index.html 파일이 자동으로 검색됩니다. index.html이 없으면 파일 나열

  3. MIME 유형 지원

  4. CACHE 지원/제어 지원 GZIP 압축 지원, 중단 점 이력서 명령 실행

  5. sub-process running

  6. 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}`);
     });
    로그인 후 복사
  7. 요청을 구체적으로 처리하고 정적 파일을 반환하는 fn을 작성합니다. url 모듈은 다음 경로를 얻습니다.
  8.  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); // 读取文件,并响应
     }
    로그인 후 복사

    index.html 찾기 지원:

     if (pathname === '/') {
      const rootPath = path.join(config.root, 'index.html');
      try{
       const indexStat = fs.statSync(rootPath);
       if (indexStat) {
        filepath = rootPath;
       }
      } catch(e) {
       
      }
     }
    로그인 후 복사
  9. 디렉토리에 액세스하면 열 출력 파일 디렉토리:
  10.  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);
     }
     }
    로그인 후 복사

    html 템플릿:

     function list() {
      let tmpl = fs.readFileSync(path.resolve(__dirname, 'template', 'list.html'), 'utf8');
      return handlebars.compile(tmpl);
     }
    로그인 후 복사
     <!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>
    로그인 후 복사
  11. 2.MIME 유형 지원

mime 모듈을 사용하여 파일 유형을 가져오고 인코딩을 설정합니다:

res.setHeader(&#39;Content-Type&#39;, mime.getType(filepath) + &#39;;charset=utf-8&#39;);
로그인 후 복사

3.

http 프로토콜 캐시:

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

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

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

max-age=60 캐시된 콘텐츠는 60초 후에 유효하지 않습니다

no-cache 데이터를 확인하려면 비교 캐시를 사용해야 하며 원본 서버에서 다시 확인하도록 강제해야 합니다
  1. no -store 모든 콘텐츠는 캐시되지 않으며 강제 캐싱이나 비교 캐싱도 실행되지 않습니다
  2. 만료: http1.0 콘텐츠, 캐시 제어는 이를 덮어쓰고 캐시가 만료되는 시기를 클라이언트에 알려줍니다
  3. ETag: 다음에 클라이언트가 요청할 때 요청 헤더에 if-none-match: etag 값을 추가하세요.

    Last- Modified: 다음 번에 클라이언트가 요청할 때 if-modified-since: Last를 추가하세요. -요청 헤더의 값 수정
  4.  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;
     }
     }
    로그인 후 복사
  5. 4. 압축

    클라이언트는 요청 헤더에서 gzip, deflate를 통해 콘텐츠를 전송하며, 서버는 이를 기반으로 콘텐츠를 압축합니다. 지원되는 압축 형식. 서버에서 지원하지 않으면 압축이 수행되지 않습니다.
  6.  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. 5. 재개 가능한 업로드

    서버는 요청 헤더의 Range: bytes=0-xxx를 사용하여 Range 요청을 하고 있는지 확인합니다. 이 값이 존재하고 유효한 경우 파일 콘텐츠의 요청된 부분만 사용됩니다. 응답 상태 코드는 206이 되어 Partial Content를 나타내며 Content-Range가 설정됩니다. 유효하지 않은 경우 요청 범위가 만족스럽지 않음을 나타내는 416 상태 코드가 반환됩니다. Range 요청 헤더가 포함되지 않은 경우 계속해서 일반적인 방식으로 응답합니다.
  8.  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
      });
     }
    로그인 후 복사
6. 전역 명령 실행

npm 링크를 통해 달성

npm 패키지 디렉터리에 대한 소프트 링크를 생성하고 이를 {prefix}/lib/node_modules/

실행 파일 생성(bin ) 소프트 링크, {prefix}/bin/{name}

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

package.json의 구성

 {
 bin: {
 "hope-server": "bin/hope"
 }
 }
로그인 후 복사

프로젝트 아래에 bin 디렉터리 희망 파일을 생성하고 yargs를 사용하여 매개변수를 전달하도록 명령줄을 구성합니다
     // 告诉电脑用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);
    로그인 후 복사
  1. 7.spawn

    index.js
  2.  const { spawn } = require(&#39;child_process&#39;);
     const Server = require(&#39;./hope&#39;);
     function init(argv) {
      // 如果配置为子进程开启服务
      if (argv.child) {
       //子进程启动服务
       const child = spawn(&#39;node&#39;, [&#39;hope.js&#39;, JSON.stringify(argv)], {
        cwd: __dirname,
        detached: true,
        stdio: &#39;inherit&#39;
       });
     
       //后台运行
       child.unref();
       //退出主线程,让子线程单独运行
       process.exit(0);
      } else {
       const server = new Server(argv);
       server.start();
      }
     }
     
     module.exports = init;
    hope.js
     if (process.argv[2] && process.argv[2].startsWith(&#39;{&#39;)) {
     const argv = JSON.parse(process.argv[2]);
     const server = new Hope(argv);
     server.start();
     }
    로그인 후 복사
  3. 에서 실행되는 하위 프로세스 실행

    8. 소스 코드 및 테스트
소스 코드 주소: hope-server

npm install hope-server -g
로그인 후 복사

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

hope-server
로그인 후 복사
관련 권장 사항:

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

다음을 사용하여 작성된 간단한 HTTP 정적 파일 서버 nodejs 및 Python

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

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

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!