极简 Node.js 入门 - 5.1 创建 HTTP 服务器
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node
使用 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
- 200 OK,表示请求正常处理
- 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 服务器的更多相关文章
- 极简 Node.js 入门 - 5.3 静态资源服务器
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - Node.js 是什么、性能有优势?
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.3 调试
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 2.2 事件
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 3.2 文件读取
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 3.3 文件写入
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 3.4 文件夹写入
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 3.5 文件夹操作
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 4.2 初识 stream
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
随机推荐
- 如何入门Pytorch之四:搭建神经网络训练MNIST
上一节我们学习了Pytorch优化网络的基本方法,本节我们将以MNIST数据集为例,通过搭建一个完整的神经网络,来加深对Pytorch的理解. 一.数据集 MNIST是一个非常经典的数据集,下载链接: ...
- [Java并发编程之美]第1章 线程基础
第1章 线程 1.1 线程与进程 进程是操作系统资源分配和调度的基本单位,但cpu资源是分配到线程的,也就是线程是CPU分配的基本单位. 线程自己的栈资源中,存放的局部变量是线程私有的,其他线程无法访 ...
- 大揭秘| 我司项目组Gitlab Flow && DevOps流程
长话短说,本文全景呈现我司项目组gitlab flow && devops Git Flow定义了一个项目发布的分支模型,为管理具有预定发布周期的大型项目提供了一个健壮的框架. Dev ...
- 突然挂了!Redis缓存都在内存中,这下完了!
我是Redis,一个叫Antirez的男人把我带到了这个世界上. “快醒醒!快醒醒!”,隐隐约约,我听到有人在叫我. 慢慢睁开眼睛,原来旁边是MySQL大哥. “我怎么睡着了?” “嗨,你刚才是不是出 ...
- web网站——nginx,LNMP部署03
nginx功能: (1)web服务器: 默认网页目录为:/usr/share/nginx/html (2)反向代理服务器: nginx代替客户端访问后端服务器,后端服务器只知道是nginx的请求,并将 ...
- archaius(2) 配置源
上一节讲到,archaius实现动态配置的核心就是定时去配置中心拉去配置内容,接下来几接就来看一下archaius内部具体是如何实现的. 首先我们来了解一下配置源,什么是配置源呢,archaius内部 ...
- php第一天-分支结构,循环结构,特殊的流程控制语句
1.单向条件分支结构 <?php if(true) { echo "yes"; } ?> 2.双向条件分支结构 <?php $a = 10; if($a < ...
- breakpad系列(2)——在Linux中使用breakpad
本文来自breakpad源码目录中doc目录下的linux_starter_guide.md,建议直接去看原文. 如何将breakpad添加进你的Linux程序 本文档是在Linux上使用Breakp ...
- 手把手教你在 TKE 集群中实现简单的蓝绿发布和灰度发布
概述 如何在腾讯云 Kubernetes 集群实现蓝绿发布和灰度发布?通常要向集群额外部署其它开源工具来实现,比如 Nginx Ingress,Traefik 等,或者让业务上 Service Mes ...
- 【PowerQuery】做了一万遍的工资条
前面已经了解了Excel.VBA.Python实现工资条,今天尝试用PQ做一遍 做之前迷惑了很久,如何能自定义长度 Table有Repeat函数,但是List没有.看来另外想办法 一步步接近目标 请 ...