學(xué)習(xí)視頻:尚硅谷2023版Node.js零基礎(chǔ)視頻教程,nodejs新手到高手
補(bǔ)充筆記:
- 計(jì)算機(jī)網(wǎng)絡(luò)|第二章:應(yīng)用層
- 計(jì)算機(jī)網(wǎng)絡(luò)|第四章:網(wǎng)絡(luò)層:數(shù)據(jù)平面
??HTTP概念
??窺探HTTP報(bào)文
-
Fiddler
-
安裝fiddler
- 安裝包下載地址
- 安裝
-
配置
- 在
Tool
的Options
里 ,找到HTTPS勾選Decrypt..
,然后同意接下來(lái)的彈窗。記得點(diǎn)OK!然后重啟??! - 設(shè)置
Web Browsers
- 在
-
使用
- 雙擊某一條則會(huì)顯示詳細(xì)信息
- 選擇
Raw
會(huì)顯示詳細(xì)信息
- 雙擊某一條則會(huì)顯示詳細(xì)信息
??請(qǐng)求報(bào)文的組成
??HTTP請(qǐng)求行
-
請(qǐng)求方法
-
URL:
Uniform Reaourse Locator
,統(tǒng)一資源定位符,其本身也是一個(gè)字符串。 -
版本號(hào)
??HTTP請(qǐng)求頭
- 格式:
頭名:頭值
??HTTP的請(qǐng)求體
??響應(yīng)報(bào)文的組成
??響應(yīng)行
??響應(yīng)頭和響應(yīng)體
- 響應(yīng)體內(nèi)容的類(lèi)型是非常靈活的,常見(jiàn)的類(lèi)型有 HTML、CSS、JS、圖片、JSON。
- 相應(yīng)頭請(qǐng)求頭這些都是不需要記住的,在MDN可查。
-
IP的介紹
- IP也稱為【IP地址】,本身是一個(gè)數(shù)字標(biāo)識(shí)。
- IP用來(lái)標(biāo)識(shí)網(wǎng)絡(luò)設(shè)備,用來(lái)實(shí)現(xiàn)設(shè)備通信。
- 端口:應(yīng)用程序的數(shù)字標(biāo)識(shí),實(shí)現(xiàn)不同主機(jī)應(yīng)用程序之間的通信。
??使用node.js創(chuàng)建HTTP服務(wù)
- 命令行
ctrl + c
停止服務(wù) - 當(dāng)服務(wù)啟動(dòng)后,更新代碼必須重啟服務(wù)才能生效
- 響應(yīng)內(nèi)容中文亂碼的解決辦法:
response.setHeader('content-type','text/html;charset=utf-8');
- 端口號(hào)被占用:
Error: listen EADDRINUSE: address already in use :::9000
1)關(guān)閉當(dāng)前正在運(yùn)行監(jiān)聽(tīng)端口的服務(wù) ( 使用較多 )
2)修改其他端口號(hào) - HTTP 協(xié)議默認(rèn)端口是 80 。HTTPS 協(xié)議的默認(rèn)端口是 443, HTTP 服務(wù)開(kāi)發(fā)常用端口有 3000,
8080,8090,9000 等。
//1. 導(dǎo)入 http 模塊
const http = require('http');
//2. 創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//response.end('Hello HTTP'); //設(shè)置響應(yīng)體
//解決響應(yīng)內(nèi)容中文亂碼的問(wèn)題
response.setHeader('content-type', 'text/html;charset=utf-8');
response.end('你好'); //設(shè)置響應(yīng)體
});
//3. 監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
//9000是端口號(hào),以下在服務(wù)啟動(dòng)成功時(shí)運(yùn)行
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
??瀏覽器查看HTTP報(bào)文
尚硅谷教程
實(shí)操
- 運(yùn)行上邊寫(xiě)的代碼,打開(kāi)對(duì)應(yīng)網(wǎng)頁(yè),F(xiàn)12檢查,查看網(wǎng)絡(luò)。
- 查看127.0.0.1細(xì)節(jié)
- 運(yùn)行表單頁(yè)提交內(nèi)容并查看請(qǐng)求體
- 查看URL查詢字符串
- 查看響應(yīng)體
??獲取HTTP請(qǐng)求報(bào)文
- 想要獲取請(qǐng)求的數(shù)據(jù),需要通過(guò)
request
對(duì)象
-
request.url
只能獲取路徑以及查詢字符串,無(wú)法獲取 URL 中的域名以及協(xié)議的內(nèi)容 -
request.headers
將請(qǐng)求信息轉(zhuǎn)化成一個(gè)對(duì)象,并將屬性名都轉(zhuǎn)化成了『小寫(xiě)』 - 關(guān)于路徑:如果訪問(wèn)網(wǎng)站的時(shí)候,只填寫(xiě)了 IP 地址或者是域名信息,此時(shí)請(qǐng)求的路徑為『 / 』
- 關(guān)于 favicon.ico:這個(gè)請(qǐng)求是屬于瀏覽器自動(dòng)發(fā)送的請(qǐng)求——獲取圖標(biāo)
??提取HTTP報(bào)文
//1. 導(dǎo)入 http 模塊
const http = require('http');
//2. 創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//獲取請(qǐng)求的方法
console.log(request.method);
//獲取請(qǐng)求的 url
console.log(request.url);// 只包含 url 中的路徑與查詢字符串
//獲取 HTTP 協(xié)議的版本號(hào)
console.log(request.httpVersion);
//獲取 HTTP 的請(qǐng)求頭
console.log(request.headers.host);
response.end('http'); //設(shè)置響應(yīng)體
});
//3. 監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
??提取HTTP報(bào)文的請(qǐng)求體(了解)
//1. 導(dǎo)入 http 模塊
const http = require('http');
//2. 創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//1. 聲明一個(gè)變量
let body = '';
//2. 綁定 data 事件
request.on('data', chunk => {
body += chunk;
})
//3. 綁定 end 事件
request.on('end', () => {
console.log(body);
//響應(yīng)
response.end('Hello HTTP');
});
});
//3. 監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
- 借助form表單
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="http://127.0.0.1:9000/index.html" method="post" > <input type="text" name="username"> <input type="text" name="password"> <input type="submit" value="提交"> </form> </body> </html>
??提取HTTP報(bào)文中URL路徑與查詢字符串
法一
//導(dǎo)入 http 模塊
const http = require('http');
//1. 導(dǎo)入 url 模塊(node.js內(nèi)置模塊)
const url = require('url');
//創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//2. 解析 request.url ,parse:解析
let res = url.parse(request.url, true);
console.log(res);
//路徑
let pathname = res.pathname;
console.log(pathname);
//查詢字符串
let keyword = res.query.keyword;
console.log(keyword);
response.end('url');
});
//監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
法二
小插曲
本來(lái)以為是05沒(méi)關(guān),但ctrlC后還是報(bào)錯(cuò)??重開(kāi)vs后OK??記得CtrlC終止后再開(kāi)新的終端??
ps:nodejs端口號(hào)占用——解決辦法
//導(dǎo)入 http 模塊
const http = require('http');
//創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//實(shí)例化 URL 的對(duì)象
let url = new URL(request.url, 'http://127.0.0.1');
//輸出路徑
console.log(url.pathname);
//輸出 keyword 查詢字符串
console.log(url.searchParams.get('keyword'));
response.end('url new');
});
//監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
??HTTP請(qǐng)求練習(xí)
//1. 導(dǎo)入 http 模塊
const http = require('http');
//2. 創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//獲取請(qǐng)求的方法
let {method} = request;
//獲取請(qǐng)求的 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('登錄頁(yè)面');
}else if(method === 'GET' && pathname === '/reg'){ // register 注冊(cè)
response.end('注冊(cè)頁(yè)面');
}else{
response.end('Not Found');
}
});
//3. 監(jiān)聽(tīng)端口 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng).. 端口 9000 監(jiān)聽(tīng)中....');
})
??HTTP響應(yīng)報(bào)文
??設(shè)置HTTP響應(yīng)報(bào)文
//導(dǎo)入 http 模塊
const http = require('http');
//創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
//1. 設(shè)置響應(yīng)狀態(tài)碼
response.statusCode = 203;
//response.statusCode = 404;
//2. 響應(yīng)狀態(tài)的描述
response.statusMessage = 'iloveyou';
//3. 響應(yīng)頭
response.setHeader('content-type', 'text/html;charset=utf-8');
// response.setHeader('Server', 'Node.js');
// response.setHeader('myHeader', 'test test test');
// response.setHeader('test', ['a','b','c']);
//4. 響應(yīng)體的設(shè)置
response.write('love');
response.write('love');
response.write('love');
response.write('love');//write可以多次調(diào)用
response.end('love'); //設(shè)置響應(yīng)體
//end不能不寫(xiě)也不能寫(xiě)多個(gè),不然會(huì)報(bào)錯(cuò)
//response.end('xxx'); //設(shè)置響應(yīng)體
});
//監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
??HTTP響應(yīng)練習(xí)
-
需求:搭建 HTTP 服務(wù),響應(yīng)一個(gè) 4 行 3 列的表格,并且要求表格有
隔行換色效果
,且點(diǎn)擊單元格能高亮顯示
-
采用html和js分離+導(dǎo)入實(shí)現(xiàn)。
-
html
完成表格樣式<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> td { padding: 20px 40px; } /* odd even交替實(shí)現(xiàn)隔行換色 */ table tr:nth-child(odd) { background: rgb(202, 219, 255); } 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> //實(shí)現(xiàn)點(diǎn)擊換色 //獲取所有的 td let tds = document.querySelectorAll('td'); //遍歷 tds.forEach(item => { item.onclick = function () { this.style.background = 'yellow'; } }) </script> </body> </html>
-
js
設(shè)置響應(yīng)//導(dǎo)入 http 模塊 const http = require('http'); const fs = require('fs'); //創(chuàng)建服務(wù)對(duì)象 const server = http.createServer((request, response) => { //讀取文件內(nèi)容 let html = fs.readFileSync(__dirname + '/10_table.html'); response.end(html); //設(shè)置響應(yīng)體 }); //監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù) server.listen(9000, () => { console.log('服務(wù)已經(jīng)啟動(dòng)....') });
??網(wǎng)頁(yè)資源的基本加載過(guò)程
- 網(wǎng)頁(yè)資源的加載都是循序漸進(jìn)的,首先獲取 HTML 的內(nèi)容, 然后解析 HTML 在發(fā)送其他資源的請(qǐng)求,如CSS,Javascript,圖片等。
- 理解了這個(gè)內(nèi)容對(duì)于后續(xù)的學(xué)習(xí)與成長(zhǎng)有非常大的幫助。
??實(shí)現(xiàn)網(wǎng)頁(yè)引入外部資源
-
這里使用的是上邊那個(gè)表格的練習(xí)例子,但把html、css、js都單獨(dú)拆開(kāi),關(guān)注外部資源引入問(wèn)題!
//導(dǎo)入 http 模塊 const http = require('http'); const fs = require('fs'); //創(chuàng)建服務(wù)對(duì)象 const server = http.createServer((request, response) => { //獲取請(qǐng)求url的路徑 let {pathname} = new URL(request.url, 'http://127.0.0.1'); if(pathname === '/'){ //讀取文件內(nèi)容 let html = fs.readFileSync(__dirname + '/10_table.html'); response.end(html); //設(shè)置響應(yīng)體 } else if(pathname === '/index.css'){ //讀取文件內(nèi)容 let css = fs.readFileSync(__dirname + '/index.css'); response.end(css); //設(shè)置響應(yīng)體 } else if(pathname === '/index.js'){ //讀取文件內(nèi)容 let js = fs.readFileSync(__dirname + '/index.js'); response.end(js); //設(shè)置響應(yīng)體 } else{ response.statusCode = 404; response.end('<h1>404 Not Found</h1>') } }); //監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù) server.listen(9000, () => { console.log('服務(wù)已經(jīng)啟動(dòng)....') });
以上寫(xiě)法可行但很麻煩,于是接下來(lái)看靜態(tài)資源服務(wù)??
??靜態(tài)資源服務(wù)
-
靜態(tài)資源
是指內(nèi)容長(zhǎng)時(shí)間不發(fā)生改變的資源 ,例如圖片,視頻,CSS 文件,JS文件,HTML文件,字體文件等。 -
動(dòng)態(tài)資源
是指內(nèi)容經(jīng)常更新的資源 ,例如百度首頁(yè),網(wǎng)易首頁(yè),京東搜索列表頁(yè)面等。 - HTTP 服務(wù)在哪個(gè)文件夾中尋找靜態(tài)資源,那個(gè)文件夾就是
靜態(tài)資源目錄
,也稱之為網(wǎng)站根目錄
。
??網(wǎng)頁(yè)中的URL
喔——又是絕對(duì)路徑相對(duì)路徑喏——
-
絕對(duì)路徑
-
相對(duì)路徑
- 關(guān)注運(yùn)行后的URL拼接方式!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>URL</title> </head> <body> <!-- 絕對(duì)路徑 --> <a href="https://www.baidu.com">百度</a> <a href="//jd.com">京東</a> <a href="/search">搜索</a> <hr> <!-- 相對(duì)路徑 --> <a href="./css/app.css">訪問(wèn)CSS</a> <a href="js/app.js">訪問(wèn)JS</a> <a href="../img/logo.png">訪問(wèn)圖片</a> <a href="../../img/logo.png">訪問(wèn)圖片</a> </body> </html>
??設(shè)置資源類(lèi)型(mime類(lèi)型)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-644212.html
/**
* 創(chuàng)建一個(gè) HTTP 服務(wù),端口為 9000,滿足如下需求
* GET /index.html 響應(yīng) page/index.html 的文件內(nèi)容
* GET /css/app.css 響應(yīng) page/css/app.css 的文件內(nèi)容
* GET /images/logo.png 響應(yīng) page/images/logo.png 的文件內(nèi)容
*/
//導(dǎo)入 http 模塊
const http = require('http');
const fs = require('fs');
const path = require('path');
//聲明一個(gè)變量
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'
}
//創(chuàng)建服務(wù)對(duì)象
const server = http.createServer((request, response) => {
if(request.method !== 'GET'){
response.statusCode = 405;
response.end('<h1>405 Method Not Allowed</h1>');
return;
}
//獲取請(qǐng)求url的路徑
let {pathname} = new URL(request.url, 'http://127.0.0.1');
//聲明一個(gè)變量
let root = __dirname + '/page';
// let root = __dirname + '/../';
//拼接文件路徑
let filePath = root + pathname;
//讀取文件 fs 異步 API
fs.readFile(filePath, (err, data) => {
if(err){
console.log(err);
//設(shè)置字符集
response.setHeader('content-type','text/html;charset=utf-8');
//判斷錯(cuò)誤的代號(hào)
switch(err.code){
case 'ENOENT':
response.statusCode = 404;
response.end('<h1>404 Not Found</h1>');
case 'EPERM':
response.statusCode = 403;
response.end('<h1>403 Forbidden</h1>');
default:
response.statusCode = 500;
response.end('<h1>Internal Server Error</h1>');
}
return;
}
//獲取文件的后綴名
let ext = path.extname(filePath).slice(1);
//獲取對(duì)應(yīng)的類(lèi)型
let type = mimes[ext];
if(type){
//匹配到了 text/html;charset=utf-8
if(ext === 'html'){
//解決亂碼問(wèn)題
response.setHeader('content-type', type + ';charset=utf-8');
}else{
response.setHeader('content-type', type);
}
}else{
//沒(méi)有匹配到
response.setHeader('content-type', 'application/octet-stream');
}
//響應(yīng)文件內(nèi)容
response.end(data);
})
});
//監(jiān)聽(tīng)端口, 啟動(dòng)服務(wù)
server.listen(9000, () => {
console.log('服務(wù)已經(jīng)啟動(dòng)....')
});
??GET和POST請(qǐng)求場(chǎng)景小結(jié)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-644212.html
??GET和POST請(qǐng)求的區(qū)別
-
GET
和POST
是 HTTP 協(xié)議請(qǐng)求的兩種方式。-
GET
主要用來(lái)獲取數(shù)據(jù),POST
主要用來(lái)提交數(shù)據(jù) -
GET
帶參數(shù)請(qǐng)求是將參數(shù)綴到 URL 之后,在地址欄中輸入 url 訪問(wèn)網(wǎng)站就是 GET 請(qǐng)求, -
POST
帶參數(shù)請(qǐng)求是將參數(shù)放到請(qǐng)求體中。 -
POST
請(qǐng)求相對(duì)GET
安全一些,因?yàn)樵跒g覽器中參數(shù)會(huì)暴露在地址欄。 -
GET
請(qǐng)求大小有限制,一般為 2K,而POST
請(qǐng)求則沒(méi)有大小限制。
-
到了這里,關(guān)于Node.js |(四)HTTP協(xié)議 | 尚硅谷2023版Node.js零基礎(chǔ)視頻教程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!