HTTP服務
本小節主要講解HTTP服務如何創建服務,查看HTTP請求&響應報文,還有注意事項說明,另外講解本地環境&Node環境&瀏覽器之間的鏈路圖示,如何提取HTTP報文字符串,及報錯信息查詢。
創建HTTP服務端
const http = require('http');const server = http.createServer((request, response) => {response.end('Hello Http Server');
});server.listen(9000, () => {console.log('服務已啟動');
});
瀏覽器輸入http://127.0.0.1:9000/
,可以看到node服務終端窗口打印日志:服務已啟動。
查看報文
打開Fiddler,可以看到瀏覽器發送的請求報文和響應報文。
請求報文:
GET http://127.0.0.1:9000/favicon.ico HTTP/1.1
Host: 127.0.0.1:9000
Connection: keep-alive
sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
sec-ch-ua-platform: "Windows"
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: image
Referer: http://127.0.0.1:9000/
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
(空格)
響應報文:
HTTP/1.1 200 OK
Date: Fri, 28 Jun 2024 06:07:06 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 17Hello Http Server
鏈路
- 引入http模塊:
const http = require('http');
這行代碼引入了Node.js
的內置http
模塊,該模塊提供了創建HTTP服務器的功能。 - 創建服務器:
http.createServer()
方法用于創建一個HTTP
服務器。它接受一個回調函數作為參數,該回調函數會在每次有請求到達服務器時被調用。回調函數有兩個參數:request
和response
,分別代表請求對象和響應對象。 - 處理請求和響應:在這個例子中,當服務器接收到任何請求時,都會執行回調函數
(request, response) => { response.end('Hello Http Server'); }
。這意味著無論你向服務器發送什么請求,它都會簡單地結束響應,并向客戶端發送字符串'Hello Http Server'
作為響應體。 - 監聽端口:
server.listen(9000, () => { console.log('服務已啟動'); });
這段代碼讓服務器開始監聽9000
端口。一旦服務器成功啟動并開始監聽指定端口,就會在控制臺打印出 ‘服務已啟動’。這意味著你的HTTP服務器現在正在監聽本機的9000
端口,等待接收HTTP
請求。 - 瀏覽器訪問:通過在瀏覽器中輸入
http://localhost:9000
來訪問這個本地運行的Node.js
服務器。瀏覽器會發送一個HTTP
請求到這個地址,你的服務器會接收到這個請求,并返回'Hello Http Server'
的消息,這將在瀏覽器窗口中顯示出來。
停止HTTP服務
當前命令行(終端)ctrl+C
更新HTTP服務
停止服務后,重新執行node腳本。(暫時)
注意事項
亂碼
response
不能返回中文,否則出現亂碼,后續通過字符集處理。
const server = http.createServer((request, response) => {response.set('content-type', 'text/html;charset-utf-8');response.end('你好');
});
端口占用
Error: listen EADDRINUSE: address already in use :::9000
結束端口
- cmd
netstat -aon|findstr "8080"
- 復制返回當前端口的
pid
進程號,比如是16712 - taskkill /pid 是16712 /f
- 終端打印
成功:已終止PID為16712的進程
更改端口
server.listen(9001, () => {console.log('服務已啟動');
});
默認端口
HTTP協議80
是默認的端口,HTTP服務常用端口有3000
,8080
,9000
。80
端口的好處是簡化訪問過程,用戶在瀏覽器中輸入網址時無需指定端口號,因為瀏覽器默認使用80端口進行HTTP請求。還可以減少配置需求,無需額外配置端口映射或轉發等。
請求行 & 請求頭
const http = require('http');const server = http.createServer((request, response) => {// 獲取請求方法console.log(request.method);// 獲取請求的urlconsole.log(request.url);// 獲取請求的版本號console.log(request.httpVersion);// 獲取Http的請求頭console.log(request.headers);response.end('Hello Http Server');
});server.listen(9000, () => {console.log('服務已啟動');
});
響應行
const http = require('http');const server = http.createServer((request, response) => {// 1. 申明let body = '';// 2. 綁定事件// 2.1 request本身就是可讀流對象// 2.2 當請求體的數據到來時,會觸發'data'事件。這里通過監聽這個事件,將接收到的數據塊chunk(Buffer類型)拼接到body字符串上。這是因為HTTP請求體可能分多個數據包到達,'data'事件可能觸發多次,每次傳遞一部分數據。request.on('data', chunk => {body += chunk;});// 3. 綁定endrequest.on('end', () => {console.log('body', body);})response.end('Hello Http Server');
});
// 使用listen方法指定服務器監聽的端口號(本例中為9000)
server.listen(9000, () => {console.log('服務已啟動');
});
由于get
請求body
中是不帶信息的,所以新建html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form action="http://127.0.0.1:9000" method="post"><input type="text" name="username"><input type="text" name="password"><input type="submit" value="提交"></form>
</body>
</html>
點擊提交,控制臺輸出:
終端打印:
提取 http 報文字符串
url.parse 提取
const http = require('http');const url = require('url');const server = http.createServer((request, response) => {// 解析request.url// console.log('request', request.url);let res = url.parse(request.url, true);console.log('res', res);// 路徑let pathName = res.pathName;// 查詢字符串let keyword = res.query.keyword;response.end('Hello Http Server');
});server.listen(9000, () => {console.log('服務已啟動');
});
new URL 構造函數提取
const http = require('http');const server = http.createServer((request, response) => {let url = new URL(request.url, 'https://www.baidu.com');console.log('url', url);// 輸出路徑console.log('pathName', url.pathname);// 取出傳參 這里以keyword為例console.log(url.searchParams.get('keyword'))response.end('Hello Http Server');
});server.listen(9000, () => {console.log('服務已啟動');
});
new URL(input[, base])
new URL(input[, base])
是一個 JavaScript
構造函數,用于從給定的輸入字符串(input)創建一個新的 URL 對象。這個函數允許你以一種標準化的方式解析和操作網址。
- input:這個參數是一個字符串,代表想要解析成URL對象的地址信息,它可以是絕對地址(如https://www.baidu.com/serach?keyword=1),也可以是相對網址(如
path/to/page?keyword=1
),如果提供的是相對地址,那么解析時就需要用到base
參數。 - base(可選參數):基準URL,當
input
是一個相對網址時,例如,如果base
是https://www.example.com/
,并且input
是path/to/page
,那么最終解析得到的完整URL
就會是https://www.example.com/path/to/page
。如果input
是一個絕對網址,那么base
參數將被忽略,即使提供了也不會影響結果。
建議使用new URL
,因為url.parse
在Node.js v22.3.0版本被棄用了。
Node.js 中文網
常見報錯信息:
錯誤代碼 | 說明 |
---|---|
ERR_INVALID_PROTOCOL | 表示提供的URL協議部分無效或不受支持。 |
ERR_UNKNOWN_URL_SCHEME | 遇到了未知的URL方案(協議),即URL的開頭部分沒有被識別 |
ERR_INVALID_CHAR | URL中包含了無效的字符 |
ERR_FILE_NOT_FOUND | 嘗試訪問的文件不存在(在涉及文件系統操作時) |
ERR_HTTP2_PROTOCOL_ERROR | HTTP/2協議層面的錯誤 |
ERR_TLS_CERT_ALTNAME_INVALID | TLS證書的備用名稱不匹配或無效 |
ERR_SSL_PROTOCOL_ERROR | SSL/TLS握手過程中發生協議錯誤。 |
ERR_SOCKET_CLOSED | 套接字意外關閉,可能是因為網絡問題或遠程端點主動關閉連接 |
ERR_CONNECTION_REFUSED | 連接被目標主機拒絕,通常是由于目標端口無服務監聽 |
ERR_CONNECTION_TIMED_OUT | 連接嘗試超時,沒有在預定時間內收到響應 |
ERR_ABORTED | 請求被用戶或程序主動中斷 |