zoukankan      html  css  js  c++  java
  • 极简 Node.js 入门

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node

    本文更佳阅读体验:https://www.yuque.com/sunluyong/node/http-server

    使用 Node.js 创建 http 服务器需要使用内置的 http 模块

    创建 web server

    Node.js 是运行在服务器环境的 JavaScript,这里的服务器更多指的是物理概念的服务器,也就是主机。使用 Node.js 创建 HTTP 服务器指的是软件概念的服务器,也就是 web server,类似于 nginx、apache

    const http = require('http');
    
    const server = http.createServer((req, res) => {
    	res.write('Hello
    ');
      res.end();
    });
    
    server.listen(9527, () => {
    	console.log('Web Server started at port 9527');
    });
    

    上面 10 行代码创建了一个最简单的 HTTP 服务器,服务器监听端口号 9527,接收到请求后返回字符串 Hello  ,可以使用浏览器或者 curl 工具测试
    image.png
    createServer 的回调函数在接收到请求后被调用

    req

    req 代表本次 http request,是一个可读流,常用有几个属性

    • url:本地请求的地址
    • method:HTTP 请求的方法(GET、POST、DELETE、PUT 等)
    • headers::请求的 HTTP header

    res

    res 代表本次http response,是一个可写流,常用的属性方法有

    • writeHead(statusCode,[, StatusMessage[, headers]]):发送响应首部,包含状态码、状态信息、响应头
    • write(chunk):向响应主体中写入字符串或者 buffer
    • end(chunk):向服务器发出信号,可以携带最后发送的数据,表明已发送所有响应头和主体,每个响应都需要调用一次
    • getHeader(name):返回指定 name 的 header
    • getHeaders():返回包含了所有 header 信息的对象
    • setHeader(name, value):设置响应头,和 writeHead() 合并,有冲突时优先使用 writeHead()
    • statusCode:设置响应 HTTP status

    返回请求信息的 web server

    上面例子中所有请求返回的结果都一样,可以对请求识别,做一些差异化的处理,下面例子展示了如何把每次请求的基本信息返回

    const http = require('http');
    
    const server = http.createServer((req, res) => {
      const { url, method, headers } = req;
    
      res.setHeader('content-type', 'text/html');
    
      res.write(`请求 URL: ${url}
    `);
      res.write(`请求方法: ${method}
    `);
      res.write(`请求 headers:${JSON.stringify(headers, null, '  ')}`);
    
      res.end('
    ');
    });
    
    server.listen(9527, () => {
      console.log('Web Server started at port 9527');
    });
    

    使用 curl 或者浏览器测试
    image.png

    返回文件内容

    上面例子和真实的 web server 还有很大差距,下面例子展示了一个最简单的返回文件内容的静态资源服务器

    const http = require('http');
    const path = require('path');
    const fs = require('fs');
    const mime = require('mime-types');
    
    // 静态资源根目录,可以设定为本地的任意有权限目录,放入 a.jpg 测试
    const ROOT_DIRECTORY = '/public';
    
    const server = http.createServer((req, res) => {
      const { url } = req;
    
      const filePath = path.join(ROOT_DIRECTORY, url);
    
      fs.readFile(filePath, (err, chunk) => {
        if (err) {
          res.writeHead(404, {
            'content-type': 'text/html',
          });
          res.end('文件不存在!');
    
        } else {
          res.writeHead(200, {
            'content-type': mime.contentType(path.extname(url)),
          });
          res.end(chunk);
        }
      });
    });
    
    server.listen(9527, () => {
      console.log('Web Server started at port 9527');
    });
    
    

    demo 中使用了 mime-types 包来根据文件名称获取文件的 Content-Type,运行 demo 需要在代码目录安装 mime-types 
    tnpm i -S mime-types

    HTTP 状态码

    1. 200 OK,表示请求正常处理
    2. 404 Not Found,表示请求资源在服务器不存在


    在测试目录下放入图片 a.jpg 使用浏览器测试 127.0.0.1:9527/a.jpg 
    image.png

    读取电影文件

    理论上读取电影文件可以使用和上面一样的代码,但实际执行会发现电影文件在完全读取到内存后才返回给浏览器,这样返回内容耗时极长,而且电影文件过大的话程序也没有办法处理,HTTP 协议是支持分段传输的(Transfer-Encoding: chunked),既然 res 是可写流,可以简单使用 stream 来做到边读取内容边返回给浏览器,而不是一次读取完成后返回

    const http = require('http');
    const path = require('path');
    const fs = require('fs');
    const mime = require('mime-types');
    
    // 静态资源根目录
    const ROOT_DIRECTORY = '/Users/undefined/node-demo/public';
    
    const server = http.createServer((req, res) => {
      const { url } = req;
    
      const filePath = path.join(ROOT_DIRECTORY, url);
    
      fs.access(filePath, fs.constants.R_OK, err => {
        if (err) {
          res.writeHead(404, {
            'content-type': 'text/html',
          });
          res.end('文件不存在!');
    
        } else {
          res.writeHead(200, {
            'content-type': mime.contentType(path.extname(url)),
          });
          fs.createReadStream(filePath).pipe(res);
        }
      });
    });
    
    server.listen(9527, () => {
      console.log('Web Server started at port 9527');
    });
    

    使用 stream 章节介绍的 fs.createReadStream() 和 pipe() 可以轻松将文件导入 http response


    Node.js 官网一次 HTTP 传输解析对 HTTP Server 做了入门讲解,顺便介绍了一些 HTTP 协议的相关知识,值得阅读

  • 相关阅读:
    C++雾中风景14:CRTP, 模板的黑魔法
    ClickHouse源码笔记1:聚合函数的实现
    C++雾中风景番外篇4:GCC升级二三事
    C++雾中风景13:volatile解惑
    AeroSpike踩坑手记1:Architecture of a Real Time Operational DBMS论文导读
    Linux 程序设计1:深入浅出 Linux 共享内存
    C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具
    C++雾中风景番外篇2:Gtest 与 Gmock,聊聊C++的单元测试
    C++雾中风景12:聊聊C++中的Mutex,以及拯救生产力的Boost
    用TensorFlow搭建一个万能的神经网络框架(持续更新)
  • 原文地址:https://www.cnblogs.com/dolphinX/p/13812960.html
Copyright © 2011-2022 走看看