>  기사  >  웹 프론트엔드  >  노드 정적 파일 서버 인스턴스에 대한 자세한 설명

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

小云云
小云云원래의
2018-03-12 09:35:001311검색

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

지원 기능:

  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);
     }
     76c82f278ac045591c9159d381de2c57
     9fd01892b579bba0c343404bcccd70fb
     93f0f5c25f18dab9d176bd4f6de5d30e
     a80eb7cbb6fff8b0ff70bae37074b813
     8f6d5a544bbc0d98e0f297ef053f784d
     ef0e6bda9678de73355aeb4407692a87
     b2386ffb911b14667cb8f0f91ea547a7{{title}}6e916e0f7d1e588d4f442bf645aedb2f
     9c3bca370b5104690d9ef395f2c5f8d1
     6c04bd5ca3fcae76e30b72ad730ca86d
     4a249f0d628e2318394fd9b75b4636b1hope-server静态文件服务器473f0a7621bec819994bb5020d29372a
     ff6d136ddc5fdfeffaf53ff6ee95f185
      {{#each files}}
      25edfb22a4f469ecb59f1190150159c6
       0e8c1c10a7257f38575c59bd16d77a1a{{name}}5db79b134e9f6b82c0b36e0489ee08ed
      bed06894275b65c1ab86501b08a632eb
      {{/each}}
     929d1f5ca49e04fdcb27f9465b944689
     36cc49f0c466276486e50c850b7e4956
     73a6ac4ed44ffec12cee46588e518a5e
  11. 2.MIME 유형 지원

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

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

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['if-modified-since'];
     // 服务器发送了etag,客户端再次请求时用If-None-Match字段来询问是否过期
     const ifNoneMatch = req.headers['if-none-match'];
     // http1.1内容 max-age=30 为强行缓存30秒 30秒内再次请求则用缓存 private 仅客户端缓存,代理服务器不可缓存
     res.setHeader('Cache-Control', 'private,max-age=30');
     // http1.0内容 作用与Cache-Control一致 告诉客户端什么时间,资源过期 优先级低于Cache-Control
     res.setHeader('Expires', new Date(Date.now() + 30 * 1000).toGMTString());
     // 设置ETag 根据内容生成的hash
     res.setHeader('ETag', hash);
     // 设置Last-Modified 文件最后修改时间
     const lastModified = stats.ctime.toGMTString();
     res.setHeader('Last-Modified', 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['accept-encoding'];
      // gzip和deflate压缩
      if (/\bgzip\b/.test(acceptEncoding)) {
       res.setHeader('Content-Encoding', 'gzip');
       return zlib.createGzip();
      } else if (/\bdeflate\b/.test(acceptEncoding)) {
       res.setHeader('Content-Encoding', 'deflate');
       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['range'];
      if (range) {
       res.setHeader('Accept-Range', 'bytes');
       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('yargs');
     const init = require('../src/index.js');
     const argv = yargs.option('d', {
     alias: 'root',
     demand: 'false',
     type: 'string',
     default: process.cwd(),
     description: '静态文件根目录'
     }).option('o', {
     alias: 'host',
     demand: 'false',
     default: 'localhost',
     type: 'string',
     description: '配置监听的主机'
     }).option('p', {
     alias: 'port',
     demand: 'false',
     type: 'number',
     default: 8080,
     description: '配置端口号'
     }).option('c', {
     alias: 'child',
     demand: 'false',
     type: 'boolean',
     default: false,
     description: '是否子进程运行'
     })
     .usage('hope-server [options]')
     .example(
     'hope-server -d / -p 9090 -o localhost', '在本机的9090端口上监听客户端的请求'
     ).help('h').argv;
     
     // 启动服务
     init(argv);
  1. 7.spawn

    index.js
  2.  const { spawn } = require('child_process');
     const Server = require('./hope');
     function init(argv) {
      // 如果配置为子进程开启服务
      if (argv.child) {
       //子进程启动服务
       const child = spawn('node', ['hope.js', JSON.stringify(argv)], {
        cwd: __dirname,
        detached: true,
        stdio: 'inherit'
       });
     
       //后台运行
       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('{')) {
     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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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