http模块
概念:
http
模块的作用:
1、服务器和普通电脑的区别在于,服务器上安装了 web
服务器软件
2、我可可以基于 Node.js
提供的 http
模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web
服务
服务器相关的概念
ip
地址
-
IP 地址
就是互联网上每台计算机的唯一地址,因此IP 地址
具有唯一性 -
IP 地址
的格式:通常用“点分十进制”表示成(a.b.c.d)
的形式,其中,a,b,c,d
都是 0~255 之间的十进制整数 -
例如:用点分十进表示的
IP
地址(192.168.1.1)
-
-
IP地址
和域名
是一一对应的关系,这份对应关系存放在一种叫做域名服务器(DNS,Domain name server)
的电脑中。使用者只需通过好记的域名访问对应的服务器即可,对应的转换工作由域名服务器实现。因此,域名服务器就是提供IP 地址
和域名之间的转换服务的服务器
注意事项:
1. 单纯使用 `IP 地址`,互联网中的电脑也能够正常工作。但是有了域名的加持,能让互联网的世界变得更加方便
2.在开发测试期间, 127.0.0.1
对应的域名是 localhost
,它们都代表我们自己的这台电脑,在使用效果上没有任何区别
-
-
每个
web 服务
都对应一个唯一的端口号 -
客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的
web 服务
进行处理
1 // 1. 导入 http 模块 2 const http = require('http') 3 // 2. 创建 web 服务器实例 4 // 调用 http.createServer() 方法,即可快速创建一个 web 服务器实例 5 const server = http.createServer() 6 // 3. 为服务器实例绑定 request 事件 7 // 为服务器实例绑定 request 事件,即可监听客户端发送过来的网络请求 8 // 使用服务器实例的 .on() 方法,为服务器绑定一个 request 事件 9 server.on('request', function (req, res) { 10 console.log('Someone visit our web server.') 11 }) 12 // 4.调用服务器实例的 .listen() 方法,即可启动当前的 web 服务器实例 13 server.listen(8080, function () { 14 console.log('server running at http://127.0.0.1:8080') 15 })
1 const http = require('http') 2 const server = http.createServer() 3 // req 是请求对象,包含了与客户端相关的数据和属性 4 server.on('request', (req, res) => { 5 // req.url 是客户端请求的 URL 地址 6 const url = req.url 7 // req.method 是客户端请求的 method 类型 8 const method = req.method 9 const str = `Your request url is ${url}, and request method is ${method}` 10 console.log(str) 11 // 调用 res.end() 方法,向客户端响应一些内容 12 res.end(str) 13 }) 14 server.listen(80, () => { 15 console.log('server running at http://127.0.0.1') 16 })
1 server.on('request', function (req, res) { 2 // res 是响应对象,它包含了与服务器相关的数据和属性 3 // 例如:将字符串发送到客户端 4 5 const str = `${req.url} -- ${req.method}` 6 7 // res.end() 方法的作用 8 // 向客户端发送指定的内容,并结束这次请求的处理过程 9 res.end(str) 10 })
解决中文乱码问题
1 const http = require('http') 2 const server = http.createServer() 3 4 server.on('request', (req, res) => { 5 // 定义一个字符串,包含中文的内容 6 const str = `您请求的 URL 地址是 ${req.url},请求的 method 类型为 ${req.method}` 7 // 调用 res.setHeader() 方法,设置 Content-Type 响应头,解决中文乱码的问题 8 res.setHeader('Content-Type', 'text/html; charset=utf-8') 9 // res.end() 将内容响应给客户端 10 res.end(str) 11 }) 12 13 server.listen(80, () => { 14 console.log('server running at http://127.0.0.1') 15 })
核心实现步骤
-
获取请求的
url
地址 -
设置默认的响应内容为
404 Not found
-
判断用户请求的是否为
/
或/index.html
首页 -
判断用户请求的是否为
/about.html
关于页面 -
设置
Content-Type
响应头,防止中文乱码 -
使用
res.end()
把内容响应给客户端
1 const http = require('http') 2 const server = http.createServer() 3 4 server.on('request', (req, res) => { 5 // 1. 获取请求的 url 地址 6 const url = req.url 7 // 2. 设置默认的响应内容为 404 Not found 8 let content = '<h1>404 Not found!</h1>' 9 // 3. 判断用户请求的是否为 / 或 /index.html 首页 10 // 4. 判断用户请求的是否为 /about.html 关于页面 11 if (url === '/' || url === '/index.html') { 12 content = '<h1>首页</h1>' 13 } else if (url === '/about.html') { 14 content = '<h1>关于页面</h1>' 15 } 16 // 5. 设置 Content-Type 响应头,防止中文乱码 17 res.setHeader('Content-Type', 'text/html; charset=utf-8') 18 // 6. 使用 res.end() 把内容响应给客户端 19 res.end(content) 20 }) 21 22 server.listen(80, () => { 23 console.log('server running at http://127.0.0.1') 24 })
模块化概念:
-
-
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块
-
-
提高了代码的复用性
-
提高了代码的可维护性
-
可以实现按需加载
-
-
自定义模块(用户创建的每个
.js
文件,都是自定 义模块) -
第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
1 // 1. 加载内置的 fs 模块 2 const fs = require('fs') 3 4 // 2. 加载用户的自定义模块 5 const custom = require('./custom.js') 6 7 // 3. 加载第三方模块,(使用第三方模块,下面会进行讲解) 8 const moment = require('moment')
1 // 被加载的模块.js 2 3 const username = '张三' 4 5 function sayHello () { 6 console.log('说话') 7 }
1 // 加载模块.js 2 3 const custom = require('./被加载的模块')
-
-
外界用
require()
方法导入自定义模块时,得到的就是module.exports
所指向的对象
1 // 记载模块.js
2 const mo = require('./被加载的模块')
4 console.log(mo) // {}
1 // 被加载的模块.js 2 3 // 当外界使用 require 导入一个自定义模块的时候,得到的成员,就是模块中,通过 module.exports 指向的那个对象 4 // console.log('我会被加载')
1 const username = 'ifer'; 2 const sum = (a, b) => a + b; 3 4 // 最佳实践,推荐写法 5 module.exports = { 6 username, 7 sum 8 }; 9 10 /* // 往 module.exports 对象上挂载了一个属性是一个字符串 11 module.exports.username = username; 12 13 // 往 module.exports 对象上挂载了一个属性是一个方法 14 module.exports.sum = (a, b) => a + b; */
1 // require 得到的结果就是这个 sum.js 文件中 module.exports 所指向的对象 2 // ./ 一定不能省略,因为 sum.js 是一个自定义模块 3 const modSum = require('./sum'); 4 5 const res = modSum.sum(1, 3); 6 console.log(res); // 4 7 8 // 这个 username 和引入的 sum.js 中的 username 没有任何关系 9 const username = 'elser'; 10 11 console.log(username); // elser 12 console.log(modSum.username); // ifer
终端命令
node index.js
1 // 加载模块.js 2 const mo = require('./被加载的模块.js') 3 4 console.log(mo) // { username: '小黑', sayHi: [Function: sayHi] }
1 // 被加载模块.js 2 3 // 当外界使用 require 导入一个自定义模块的时候,得到的成员,就是模块中,通过 module.exports 指向的那个对象 4 // console.log(module) 5 6 // 向 module.exports 对象上挂载 username 属性 7 module.exports.username = 'zs' 8 9 // 向 module.exports 对象上挂载 sayHello 方法 10 module.exports.sayHello = function () { 11 console.log('Hellp') 12 } 13 14 // 使用 module.exports 指向一个全新的对象 15 module.exports = { 16 username: '小黑', 17 sayHi() { 18 console.log('小黑') 19 } 20 }
1 console.log(exports) 2 3 console.log(module.exports) 4 5 // 默认情况下,`exports` 和 `module.exports` 指向同一个对象 6 console.log(exports === module.exports) // true
1 // 将私有成员共享出去 2 exports.username = 'zs' 3 4 // 直接挂载方法 5 exports.sayHello = function () { 6 console.log('Hellp') 7 }
-
-
注意:为了防止混乱,建议大家不要在同一个模块中同时使用
exports
和module.exports
1 exports.username = 'Tom' // 不会被打印 2 3 module.exports = { 4 gender: '男', 5 age: 22 6 } 7 8 module.exports.username = 'Tom' 9 10 // 不会被执行 11 exports = { 12 gender: '男', 13 age: 22 14 } 15 16 17 // 两个都会执行 18 module.exports.username = 'Tom' 19 20 exports.gender = '男' 21 22 // 三个都会打印 23 exports = { 24 gender: '男', 25 age: 22 26 } 27 28 module.exports = exports 29 module.exports.username = 'Tom'
CommonJS
模块化规范
-
Node.js
遵循了CommonJS
模块化规范,CommonJS
规定了模块的特性和各模块之间如何相互依赖 -
CommonJS
规定: -
每个模块内部,
module
变量代表当前模块 -
module
变量是一个对象,它的exports
属性(即module.exports
)是对外的接口 -
加载某个模块,其实是加载该模块的
module.exports
属性。require() 方法用于加载模块