1

极简 Node.js 入门 - 5.1 创建 HTTP 服务器

 3 years ago
source link: https://www.cnblogs.com/dolphinX/p/13812960.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

极简 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\n');
  res.end();
});

server.listen(9527, () => {
	console.log('Web Server started at port 9527');
});

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

image.png

createServer 的回调函数在接收到请求后被调用

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

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

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}\n`);
  res.write(`请求方法: ${method}\n`);
  res.write(`请求 headers:${JSON.stringify(headers, null, '  ')}`);

  res.end('\n');
});

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 协议的相关知识,值得阅读


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK