极简 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 工具测试

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}\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 或者浏览器测试

返回文件内容

上面例子和真实的 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 

读取电影文件

理论上读取电影文件可以使用和上面一样的代码,但实际执行会发现电影文件在完全读取到内存后才返回给浏览器,这样返回内容耗时极长,而且电影文件过大的话程序也没有办法处理,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 协议的相关知识,值得阅读

极简 Node.js 入门 - 5.1 创建 HTTP 服务器的更多相关文章

  1. 极简 Node.js 入门 - 5.3 静态资源服务器

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  2. 极简 Node.js 入门 - Node.js 是什么、性能有优势?

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  3. 极简 Node.js 入门 - 1.3 调试

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  4. 极简 Node.js 入门 - 2.2 事件

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  5. 极简 Node.js 入门 - 3.2 文件读取

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  6. 极简 Node.js 入门 - 3.3 文件写入

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  7. 极简 Node.js 入门 - 3.4 文件夹写入

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  8. 极简 Node.js 入门 - 3.5 文件夹操作

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  9. 极简 Node.js 入门 - 4.2 初识 stream

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

随机推荐

  1. 浅谈备受开发者好评的.NET core敏捷开发工具,讲讲LEARUN工作流引擎

    通俗来讲,所谓一个工作流管理系统,如果将其拆分出来一个个单讲话,大致可理解为由工作流引擎.工作流设计器.流程操作.工作流客户界面. 流程监控.表单设计器.与表单的集成以及与应用程序的集成等几个部分组成 ...

  2. shell小技巧(3)复制文件到其他主机

    复制一个文件nfsclient.sh到主机172.18.117.162的/tmp目录下 scp -P22 /tmp/nfsclient.sh  root@172.18.117.162:/tmp -P2 ...

  3. 使用jackson解析json串得到树模型,然后遍历树模型获得需要的数据

    Problem:从网址 http://quotes.money.163.com/hs/service/marketradar_ajax.php?host=http%3A%2F%2Fquotes.mon ...

  4. Python 3.8.1 各版本下载地址

    Version Operating System Description MD5 Sum File Size GPG Gzipped source tarball Source release   f ...

  5. jzoj1497. 景点中心

    Description 话说宁波市的中小学生在镇海中学参加计算机程序设计比赛,比赛之余,他们在镇海中学的各个景点参观.镇海中学共有n个景点,每个景点均有若干学生正在参观.这n个景点以自然数1至n编号, ...

  6. python语法,基础

    1.用缩进表达代码逻辑:推荐缩进4个空格 2.注释和续行与shell一样 在pycharm中,按ctrl + / 可以快速添加/取消注释 3.多个语句书写在同一行,可以使用分号进行分割.但不推荐 输出 ...

  7. [LeetCode]121、122、309 买股票的最佳时机系列问题(DP)

    121.买卖股票的最佳时机 题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意 ...

  8. Python中的相对路径的表示方法

    2020/6/3 举例: 现在 6-2.py 想使用 /data/lastfm-2k/user_artists.dat 因为 6-2.py 和 data 是同一级目录,所以正确的写法应该是:

  9. 面向对象技术-原文转载自jingwhale

    面向对象技术 --原文转载自jingwhale,文章底部附原文链接 对象是面向对象的程序设计的核心,它由描述状态的属性(变量)和用来实现对象行为的方法(函数)组成,完成了从数据模型到处理模型的结合与统 ...

  10. 我搭建了一套企业级私有Git服务,抗住了每天上万次攻击!

    写在前面 事情是这样的,今年疫情期间,我在某云购买了一套服务器,做什么呢?不是用来部署项目,也不是用来搭建网站,而是用来做代码备份和管理.没错,都是我个人的代码,也许你会说,你个人能有多少代码啊?确实 ...