(一)什么是HTTP协议?
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议
(二)请求报文结构
请求体有非空和空的
请求行
1、 请求方法:
2、URL:
(Uniform Resource Locator,统一资源定位器)
URL组成:协议名+主机名(定位网络上的计算机)+路径(定位服务器中的资源)
3、 HTTP版本号:
请求头
1、键值对格式
2、主要记录了浏览器相关信息
3、User-Agent:记录浏览器的平台、版本号
4、Accept:浏览器能够处理的数据类型
5、Accept-Encoding:当前浏览器能支持浏览器的方式
6、Accept-Language:当前浏览器所支持的语言
7、Upgrade-Insecure-Request:升级HTTP为HTTPS提高安全性
HTTP 标头(header) - HTTP | MDN (详细学习HTTP)
请求体
请求体的格式没有定义,用的比较多的是键值对(JSON格式)
(三)响应报文结构与响应行
响应行结构:
响应状态码:
响应状态描述:基本和响应状态码对应
HTTP 响应状态码 - HTTP | MDN (陌生响应状态码可在此处查询)
响应头:
1、Server:记录服务器所使用的技术
2、Date:记录响应时间
3、Content-Type:声明响应体格式与字符集。(重要)
响应体:
常见的响应体格式:
扩展:
HTTP抓取工具:
Fiddler抓包工具简介,安装及使用教程详解_Sunny蔬菜小柠的博客-CSDN博客
==================================分隔线=================================
(一)创建HTTP服务端
//导入Http模块
const http = require('http');
//创建服务对象
const server = http.createServer((request,response)=>{
response.end('Hello HTTP Server');//设置响应体
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
可以看到9000端口已经被node.js的脚本程序占用了,那么谁能给他发送请求呢?浏览器能!
(二)HTTP服务的注意事项:
找到被占用的端口,记住他的PID ,打开任务管理器
找到对应的PID,右击停止。
(三)用过浏览器查看HTTP报文
网页右击检查
写一个页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:9000/" method="post" >
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
按提交就会跳转:http://127.0.0.1:9000/
源代码是这一串字符串
(四)获取HTTP请求报文
(五)提取URL中的路径(第一种方法)
//导入Http模块
const http = require('http');
//1、导入url模块
const url = require('url');
//创建服务对象
const server = http.createServer((request,response)=>{
//2、解析request.url
let res = url.parse(request.url,true)
//路径
let pathname=res.pathname;
//查询字符串
let keyword = res.query.keyword;
console.log(keyword)
response.end('url')
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
提取URL中的路径(第二种方法)
//导入Http模块
const http = require('http');
//创建服务对象
const server = http.createServer((request,response)=>{
//实例化URL对象
let url= new URL(request.url,'http://127.0.0.1');
//输出路径
console.log(url.pathname);
//输出字符串
console.log(url.searchParams.get('keyword'));
response.end('url')
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
HTTP请求联系
//导入Http模块
const http = require('http');
//创建服务对象
const server = http.createServer((request,response)=>{
//获取请求方法
let {method}= request;//解构赋值的方式,因为method是request里面的方法
//获取请求url路径
let {pathname} = new URL(request.url,'http://127.0.0.1');
//乱码处理
response.setHeader('content-type','text/html;charset=utf-8')
//判断
if (method ==='GET' && pathname==='/login'){
//登录情形
response.end('登录页面');
}else if (method ==='GET'&& pathname==='/reg') {
response.end('注册页面');
}else {
response.end('Not Found')
}
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
(五)设置HTTP响应报文
//导入Http模块
const http = require('http');
//创建服务对象
const server = http.createServer((request,response)=>{
//设置响应那个状态码
response.statusCode=203;
//设置响应状态的描述
response.statusMessage='nihao'; //在一般状态下,响应状态描述一般跟响应码一一对应,所以这一块了解即可
//响应头
response.setHeader('content-type','text/html;charset=utf-8')
//响应头还可以设置别的
response.setHeader('Server','Node.js')//Server是用来标识服务端的名字
//自定义响应头
response.setHeader('myHeader','woshichengxuyuan')
//设置多个同名响应头
response.setHeader('test',['a','b','c']);
//响应体设置
response.write('nihao');//write方法可以多次调用,end方法只能有一个
response.write('hello');
response.end('Not Found')//设置响应体
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
HTTP响应练习
js代码:
//导入Http模块
const http = require('http');
const fs = require('fs')
//创建服务对象
const server = http.createServer((request,response)=>{
//读取文件内容
let html= fs.readFileSync(__dirname+'/01.html')
response.end(html)//设置响应体
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
td{
padding: 20px 40px;
}
table tr:nth-child(odd){
background: #aef;
}
table tr:nth-child(even){
background: #fcb;
}
table,td{
border-collapse: collapse;
}
</style>
</head>
<body>
<table border="1">
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
<script>
//获取所有的td
let tds = document.querySelectorAll('td');
//遍历
tds.forEach(item =>{
item.onclick = function(){
this.style.background='#222'
}
})
</script>
</body>
</html>
练习:实现网页引入外部资源
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="01.css">
</head>
<body>
<table border="1">
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
<script src="01.js"></script>
</body>
</html>
css代码:
td{
padding: 20px 40px;
}
table tr:nth-child(odd){
background: #aef;
}
table tr:nth-child(even){
background: #fcb;
}
table,td{
border-collapse: collapse;
}
js代码:
//获取所有的td
let tds = document.querySelectorAll('td');
//遍历
tds.forEach(item =>{
item.onclick = function(){
this.style.background='#222'
}
})
功能代码:
//导入Http模块
const http = require('http');
const fs = require('fs')
//创建服务对象
const server = http.createServer((request,response)=>{
//获取请求url的路径
let {pathname} = new URL(request.url,'http://127.0.0.1');
if (pathname==='/'){
//读取文件内容
let html= fs.readFileSync(__dirname+'/01.html')
response.end(html)//设置响应体
}else if(pathname==='/01.css'){
//读取文件内容
let css= fs.readFileSync(__dirname+'/01.css')
response.end(css)//设置响应体
}else if (pathname==='/01.js'){
//读取文件内容
let js= fs.readFileSync(__dirname+'/01.js')
response.end(js)//设置响应体
}else {
response.statusCode=404
response.end('<h1>404 Not Found</h1>')
}
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
结果:
html响应html页面
css响应css页面
js响应js页面
但是这种方法很麻烦,要写很多if-else,还有更好的方法吗?
(六)用HTTP模块搭建静态资源服务
主要代码:
//导入Http模块
const http = require('http');
const fs = require('fs')
//创建服务对象
const server = http.createServer((request,response)=>{
//获取请求url的路径
let {pathname} = new URL(request.url,'http://127.0.0.1');
//拼接文件路径
let filePath=__dirname+'/page'+pathname;
// console.log(filePath)
//读取文件fs 异步API
fs.readFile(filePath,(err,data)=>{
if (err){
response.statusCode=500;
response.end('读取失败');
return;
}
//响应文件内容
response.end(data)
})
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
结果:
(七) 网站根目录或静态资源目录
HTTP 服务在哪个文件夹中寻找静态资源,那个文件夹就是 静态资源目录,也称之为 网站根目录
(八)网页URL之绝对路径
第一种和第三种用的比较多。
(八)网页URL之相对路径
./是当前文件夹,../是上一级目录
(九)MIME类型(媒体类型)资源类型
mime 类型结构: [type]/[subType]
html: 'text/html',
css: 'text/css',
js: 'text/javascript',
png: 'image/png',
jpg: 'image/jpeg',
gif: 'image/gif',
mp4: 'video/mp4',
mp3: 'audio/mpeg',
json: 'application/json'
规范一点写法,但是没必要。
//导入Http模块
const http = require('http');
const fs = require('fs')
const path=require('path')
let mimes={
html: 'text/html',
css: 'text/css',
js: 'text/javascript',
png: 'image/png',
jpg: 'image/jpeg',
gif: 'image/gif',
mp4: 'video/mp4',
mp3: 'audio/mpeg',
json: 'application/json'
}
//创建服务对象
const server = http.createServer((request,response)=>{
//获取请求url的路径
let {pathname} = new URL(request.url,'http://127.0.0.1');
//拼接文件路径
let filePath=__dirname+'/page'+pathname;
//读取文件fs 异步API
fs.readFile(filePath,(err,data)=>{
if (err){
response.statusCode=500;
response.end('读取失败');
return;
}
//获取文件后缀名
let ext= path.extname(filePath).slice(1)
//获取对应的类型
let type = mimes[ext];
if (type){
//匹配到了
response.setHeader('content-type',type);
}else{
//匹配不到
response.setHeader('content-type','application/octet-stream')
}
//响应文件内容
response.end(data)
})
});
//监听端口,启动服务
server.listen(9000,()=>{
console.log('服务已启动')
});
(十)GET和POST的区别
- 在地址栏直接输入 url 访问
- 点击 a 链接
- link 标签引入 css
- script 标签引入 js
- img 标签引入图片
- form 标签中的 method 为 get (不区分大小写)
- ajax 中的 get 请求
- form 标签中的 method 为 post(不区分大小写)
- AJAX 的 post 请求
GET和POST请求的区别
- 作用不同:GET 主要用来获取数据,POST 主要用来提交数据
- 参数位置不同:GET 带参数请求是将参数缀到 URL 之后,在地址栏中输入 url 访问网站就是 GET 请求,POST 带参数请求是将参数放到请求体中
- 安全性不同:POST 请求相对 GET 安全一些,因为在浏览器中参数会暴露在地址栏
- GET 请求大小有限制,一般为 2K,而 POST 请求则没有大小限制