九、HTTP模块
1、基本概念
1.1 交互模式
B/S:指基于 浏览器(Browser) 和 服务器(Server) 这种交互形式
C/S:指基于 客户端(Client) 和 服务器(Server) 这种交互形式
1.2 终端的概念:
服务器:在网络节点中,专门对外提供资源服务的机器;
客户端:在网络节点中,专门用来消费服务的一台电脑;
1.3 静态资源与动态资源:
静态资源:服务器端只需要读取并直接发送给客户端、不需要进一步处理的资源。
动态资源:服务器端没有现成的资源,需要服务器端动态生成的资源。
2、Web应用架构
Client - 客户端,一般指浏览器,浏览器可以通过 HTTP 协议向服务器请求数据。
Server - 服务端,一般指 Web 服务器,可以接收客户端请求,并向客户端发送响应数据。
Business - 业务层, 通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等。
Data - 数据层,一般由数据库组成。
3、http协议通信模型
数据流形式:请求 -> 处理 -> 响应
请求:由客户端发起请求;
处理:由服务器端处理请求;
响应:服务器端把处理的结果,通过网络发送给客户端
HTTP 协议会话过程的 4 个步骤
●建立连接:客户端的浏览器向服务端发出建立连接的请求,服务端给出响应就可以建立连接了。
●发送请求:客户端按照协议的要求通过连接向服务端发送自己的请求。
●给出响应:服务端按照客户端的要求给出应答,把结果(HTML 文件)返回给客户端。
●关闭连接:客户端接到应答后关闭连接
4、URL组成
URL是统一资源定位符,一种特殊类型的URI,根据一个 url 能够在全球确定一个唯一的资源,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
4.1 组成
协议://子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值
4.2 http协议简介
HTTP(Hyper Text Transfer Protocol)< 超文本传输协议> 的缩写
http与https的区别
相同点:http协议和https,都是超文本传输协议,
不相同点:
1)http的参数信息是明文传输,而https的参数信息是加密传输,
2)https则是具有安全性的ssl加密传输协议。
3)端口号不同http是80,https是443
http请求信息的组成
● 请求方法URI协议/版本
● 请求头(Request Header)
● 请求正文
http响应信息的组成
●状态行:
●消息报头:响应报头后述
●响应正文:服务器返回的资源内容
常见的状态码
200 OK // 客户端请求成功
301 Moved Permanently //永久重定向
304 Not Modified //请求资源未发生改变
307 Temporary Redirect //临时重定向
400 Bad Request // 客户端请求有语法错误,不能被服务器所理解
401 Unauthorized // 请求未经授权,这个状态代码必须和WWW-Authenticate 报头域一起使用
403 Forbidden // 无权限访问,服务器收到请求,但是拒绝提供服务
404 Not Found // 请求资源不存在,eg:输入了错误的 URL
500 Internal Server Error // 服务器发生不可预期的错误
502 Bad Gateway //请求超时
503 Server Unavailable // 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
5、Path模块
path模块,做路径的规范(拼接、获取某一部分,获取绝对路径/相对路径)
引入方式:
const path=require("path");
常用方法
1、path.basename(path[, ext])
获取当前路径参数的最后一部(即文件名字/文件夹的名字),以“/”为截取目标
参数
path,操作路径(绝对路径/相对路径)
ext,截取内容,此内容是被忽略掉,注:截取是从右向左一一匹配。匹配不上截取失败。
console.log(__filename);
console.log(path.basename(__filename));//03_Path模块.js
console.log(path.basename(__dirname));//1.29
console.log(path.basename("/a/b/c/"));//c
console.log(path.basename(__filename,"s"));//03_Path模块.j
console.log(path.basename(__filename,"ss"));//03_Path模块.js
console.log(path.basename(__filename,"块.js"));//03_Path模块
2、path.delimiter
获取当前运行环境的结束符
windows的结束符是;
其它系统是 :
console.log(path.delimiter);
3、path.dirname(path)
获取当前目录的父级目录
console.log(path.dirname(__filename));//D:\Work space\project-node\1.29
console.log(path.dirname("./a/b/c"));
4、path.extname(path)
获取文件路径的后缀名
注:它是以最后一个“.”作为截取,截取后面的部分
console.log(path.extname("./a/a/b"));//空
console.log(path.extname(__filename));//.js
console.log(path.extname(__dirname));//.29(特例)
console.log(path.extname("./a/b/c/d/e.f.g"));//.g(特例)
console.log(path.extname("./a/b/c/d/e.f."));//.(特例)
5、path.isAbsolute(path)
判断当前路径是否是绝对路径,返回值是布尔类型
注:此方法是以"/"为判断依据,如果是“/”开始责备视为绝对路径
console.log(path.isAbsolute(__dirname));//true
console.log(path.isAbsolute("/a/v/c/x"));//true
console.log(path.isAbsolute("D:/a/v/c/x"));//true
console.log(path.isAbsolute("//a/b/c/d"));//true
console.log(path.isAbsolute("./a/v/c/x"));//false
console.log(path.isAbsolute("../a/v/c/x"));//false
console.log(path.isAbsolute("D/a/v/c/x"));//false
6、path.join([…paths])
路径的拼接,返回值是一个路经字符串形式
参数路劲与参数路径采用,隔开,可以不使用"/"
注,路径的拼接支持"…/","./",会将其转义
console.log(path.join("a","b"));// a\b
console.log(path.join(__dirname,"b"));//D:\Work space\project-node\12.26\b
console.log(path.join(__dirname,"1.js"));//D:\Work space\project-node\1.29\1.js
console.log(path.join(__dirname,"../../../a/b/index.html"));//D:\a\b\index.html
console.log(path.join(__dirname,__dirname,"a","b"));
console.log(path.join(__dirname,"aa","1.js"));//D:\Work space\project-node\1.29\aa\1.js
console.log(path.join(__dirname,__filename));//D:\Work space\project-node\1.29\D:\Work space\project-node\1.29\03_Path模块.js
7、path.normalize(path)
规范化路径
注:此方法只支持 "./"的路径规范。
console.log(path.normalize(__filename));//绝对路径没有任何效果
console.log(path.normalize("./a/b/c/s"));//以"."开始的相对路径,此方法可以将"./"省略。
console.log(path.normalize("../a/b/d/c"));//以"../"开始的相对路径,此方法只会将"/"转换为"\"
console.log(path.normalize("ff/ee/../../a/b/c/d"));//a\b\c\d
console.log(path.normalize("/a/b/c/d/e"));// \a\b\c\d\e
console.log(path.normalize("//a/b/c/d"));// \\a\b\c\d
8、path.parse(path)
将路径参数转换为对象,对象中包含(盘符,父级路径、文件名全名,后缀名、文件名)
console.log(path.parse(__filename));
6、URL模块
url模块推荐使用 WHATWG 标准的新API。
组成:
协议://子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标识
URL对象:返回一个URL对象,对象中包含(源地址、主机地址,协议,域名+端口,域名,端口号,资源路由,参数字符串,参数对象,标识符)
**注:**参数字符串会默认将中文字符进行编码操作
语法:
new URL(input[, base]);
input:要解析的绝对或相对的 URL。,注:如果input为绝对url,则不需要base属性,否则需要
base:主机地址
**注:**使用URL模块不需要引入,直接创建实例就可以生成URL对象
let urlstr=`https://www.baidu.com:1234/a/b/c/index.html?username=rypy&pwd=123456#aaa`;
let urlObj=new URL(urlstr);//创建一个URL实例,会将url类型的字符串转换为URL对象类型。
console.log(urlObj);
console.log(urlObj.origin);
console.log(urlObj.protocol);
console.log(urlObj.pathname);
注:searchParams类型的存储形式是Map数据结构。
console.log(urlObj.searchParams.get("username"));
let urlstr=`/a/b/c/index.js`;//目录(路由/资源路由)
//如果url字符串是相对URL不是绝对URL,则new实例的时候需要第二个参数,设置一个虚拟的服务器地址。
let urlObj=new URL(urlstr,`http://abc.abc.abc:1234`);
console.log(urlObj);
7、Querystring模块
querystring模块,用来解析和格式化url携带的参数。
1、引用.parse(str[, sep[, eq[, options]]])
将字符串类型的URL序列参数(浏览器地址栏的参数形式),转换为Object类型的对象,自带中文解码操作,可以将中文字符由原来的编码解析为中文汉字。
参数
str URL格式的字符串参数序列
sep,设置将URL字符串分割为对象的键值对的标志,默认值是"&"
eq,设置生成对象的键名与键值的分割标志,默认值是“=”
let urlstr=`username=rypy&pwd=123456`;
console.log(qs.parse(urlstr));//[Object: null prototype] { username: 'rypy', pwd: '123456' }
console.log(qs.parse(urlstr,"="));//[Object: null prototype] { '123456': '', username: '', 'rypy&pwd': '' }
let urlstr=`username:"我是web"|pwd:123456`;
console.log(qs.parse(urlstr,"|",":"));
2、引用.stringify(obj[, sep[, eq[, options]]])
将Object类型的对象转换为URL格式的参数序列字符串。自带编码功能,可以将中文字符转换为十六进制的值。
参数
obj 需要转换的对象
sep,设置拼接字符串的键值对的符号 默认值是“&”
eq,设置拼接字符串的键名与键值的符号 默认值是“=”
let user={username:"我是web",pwd:123456};
console.log(qs.stringify(user));
let urlstr=qs.stringify(user);
console.log(qs.parse(urlstr));
3、引用.escape(str)
将中文字符进行编码操作
let str=`我是web学生`;
console.log(qs.escape(str));
4、引用.unescape(str)
将编码后的中文字符进行解码操作
let str=`我是web学生`;
let str2=qs.escape(str);
console.log(qs.unescape(str2));
8、http原生创建启动服务代码
使用http模块 创建服务基本步骤3步
//1、引入http模块
const http=require("http");
//2、创建http实例
//创建实例采用createServer(callback)
//回调函数中含有两个形参,req,代表请求对象(request),res代表响应对象(response)
//request请求对象,用来获取请求相关信息的,请求携带的参数,请求头部的信息等。
//response响应对象,用来给客户端发送响应信息,响应头部,响应内容等
const server= http.createServer((req,res)=>{});
//3、设置端口号 (1~65398)
采用listen()方法
//参数一,端口号,
//参数二,局域网IP地址(本地TCP/IP地址),可以省略,省略的情况下域名为localhost,IP地址为127.0.0.1。
参数三,回调函数,可以省略,功能,启动服务的时候,服务器正常启动,可执行此回调函数。
server.listen(1234,"10.10.89.85",()=>{
console.log("服务器已启动,IP地址是10.10.89.85,端口号1234");
});
9、http原生响应内容到浏览器
const http=require("http");
const server=http.createServer((req,res)=>{
//在node原生http模块中,如果只响应一个首页路由,可以直接书写响应内容。
//当需要给浏览器返回中文汉字的时候,必须要设置响应头部的编码格式。
//设置响应头部,采用的方法writeHead()
//writeHead() 参数1,设置响应状态码 ,参数2,设置状态的码的消息(可省略,但是不能是中文),参数3 对象的形式,设置 Content-Type属性的值,其值可以设置资源文件的类型。
//res.writeHead(400,"this is a big error!",{"Content-Type":"text/html;charset=utf8;"});//设置响应html文件的MIME类型。
res.writeHead(400,"this is a big error!",{"Content-Type":"text/plain;charset=utf8;"});//设置响应html文件的MIME类型。
//MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,又称文档类型。功能:告知浏览器,当前响应的文件类型,
//res.write(),向浏览器端响应输出内容。//注:write()可以与write()方法本身和end(),同时返回响应内容,而且是可以做拼接操作。
res.write("我是write第一个方法响应的内容");
res.write("我是write第二个方法响应的内容");
//res.end();//结束响应并向浏览器端传送,参数内容,且参数内容可以响应到浏览器内容区。
res.end(`<h1 style="color:red">hello node!</h1>我检查口罩!`);
//注:end方法必须要放置在响应内容的最后面。否则会报错。
//注:如果修改了服务器端代码,必须重新启动服务。
});
server.listen(1234);
//注:如果在启动的时候出现 address already in use 10.10.89.85:1234,就代表域名和端口号重复,目前有该域名和端口号的服务启动,出现错误的解决办法:修改域名/IP,或者修改端口号。
//命令行终止node启动的服务 ctrl+c
10、http模块响应资源文件
MIME类型,是多用途互联网邮件扩展类型,又称文档类型,功能告诉浏览器,我当前服务器传递的资源是什么类型,不同的类型,浏览器会做不同的响应。
常见的MIME类型(通用型):
名称 | 文件格式 | MIME类型 |
---|---|---|
超文本标记语言文本 | .html | text/html |
xml文档 | .xml | text/xml |
XHTML文档 | .xhtml | application/xhtml+xml |
普通文本 | .txt | text/plain |
RTF文本 | .rtf | application/rtf |
PDF文档 | application/pdf | |
PNG图像 | .png | image/png |
Microsoft Word文件 | .word | application/msword |
GIF图形 | .gif | image/gif |
JPEG图形 | .jpeg,.jpg | image/jpeg |
css文件 | .css | text/css |
Json文件 | .json | application/json |
JS文件 | .js | text/JavaScript |
const http=require("http");
const fs=require("fs");
const path=require("path");
http.createServer(async (req,res)=>{
let [err,data] =await new Promise(resolve=>{
fs.readFile(path.join(__dirname,"./css/index.css"),"utf8",(err,data)=>{
// if(err)resolve(err);
// else resolve(data);
resolve([err,data]);
});
});
if(err){
res.writeHead(200,"ok",{"Content-type":"text/html;charset=utf8;"});
}else{
res.writeHead(200,"ok",{"Content-type":"text/css"});
res.end(data);
}
}).listen(520);
11、http响应静态资源
const http=require("http");
const path=require("path");
const fs=require("fs");
http.createServer(async (req,res)=>{
//req.url,获取 资源路由和参数,返回值是一个字符串
let [urlPath,params]=req.url.split("?");//将资源路由和参数,进行分割
console.log(params);
let htmlText="";//此变量用来接收读取文件的内容
switch(urlPath){
//注:在服务器端定义路由一定要带"/",如"/index.css",
//注:"/",通常被称作 主路由
case "/index.css":
res.writeHead(200,"ok",{"Content-type":"text/css"});
htmlText=await getFileData("css/index.css");
break;
case "/jquery.min.js":
res.writeHead(200,"ok",{"Content-type":"text/javascript"});
htmlText=await getFileData("js/jquery.min.js");break;
case "/index.html":
res.writeHead(200,"ok",{"Content-type":"text/html"});
htmlText=await getFileData("html/index.html");break;
}
if(htmlText[0]){
res.end(htmlText[0]);
}else{
res.end(htmlText[1]);
}
}).listen(1111,"10.10.10.166");
//读取静态资源文件
function getFileData(filepath) {
return new Promise(resolve=>{ fs.readFile(path.join(__dirname,"public",filepath),"utf8",(err,data)=>{
resolve([err,data]);
});
});
}
12、http模参数的获取
http模块获取get请求参数
**req.url:**获取资源路由和参数
"/":一般再服务器端称之为主路由,一般用来响应首页
如果不设置服务器端IP地址,则使用localhost或127.0.0.1
const http=require("http");
const qs=require("querystring");
const {getFilePage}=require("./model/fileControl");
http.createServer(async (req,res)=>{
let err="";
let htmlText="";
let htmlType="";
let [urlPath,params]=req.url.split("?");
switch(urlPath){
/* 静态资源部署区域 */
case "/":;
case "/index.html":
htmlType="text/html";
[err,htmlText]= await getFilePage("index.html");
break;
case "/jquery.min.js":
htmlType="text/javascript";
[err,htmlText] = await getFilePage("./js/jquery.min.js");
break;
case "/index.js":
htmlType="text/javascript";
[err,htmlText]= await getFilePage("./js/index.js");
break;
/* 动态资源获取区域 */
case "/reguest":
htmlType="application/json";
let user=qs.parse(params);//将url参数类型的对象转换为真正对象
if(user.username==="admin"&&user.pwd==="123456"){
htmlText=JSON.stringify({msg:"登录成功"});
}else{
htmlText=JSON.stringify({msg:"登录失败"});
}
}
if(err){
htmlType="text/html";
htmlText="服务器端出现错误!";
}
res.writeHead(200,"ok",{"Content-Type":htmlType});
res.end(htmlText);//只能以字符串的形式返回JSON格式的数据。
}).listen(2222,"10.10.10.166");
http模块获取post请求参数
在http原生种如果需要响应post请求并获取参数,需要做事件监听。
**注:**如果监听了data事件就必须监听end事件。且如果监听了end事件,响应的end方法必须写在请求的end事件中,那么当监听了end事件以后,由于请求事件的监听是用同一个请求,所以data事件种回调函数的参数值,可以在end种使用。
req.on("data",(data)=>{});
req.on("end",async ()=>{//end事件中,完成路由的响应
//注:如果监听了end事件,响应的end方法必须写在请求的end事件中
res.end(htmlText);
});
十、服务器简介
常见服务器包括Apache、Apache Tomcat、IIS、Node、Nginx、WebLogic、kangle等。