HTTP入門(三):使用Nodo.js腳本實現簡易伺服器
HTTP入門(三):使用Nodo.js腳本實現簡易伺服器
- 本文通過簡單的Node.js腳本模擬伺服器請求與響應原理。
- 本文主要目的是對學習內容進行總結以及方便日後查閱。
- 本文所引用的圖片和文字版權歸原作者所有,侵權刪。
- 如有錯誤請在下方評論區指出,歡迎積極討論。
前言
- 硬體伺服器:我們的電腦就是一個伺服器。和普通的伺服器的區別是:真正的伺服器CPU可能有128G核,32、64、128G內存。沒有GUI,沒有顯示器,用ssh遠程登錄,本質還是電腦
- 軟體伺服器:伺服器上的軟體。
伺服器你已經有了,你使用的電腦就是伺服器。但是你還沒有提供 HTTP 服務的「程序」。
用腳本就可以提供 HTTP 服務,不管是 Bash 腳本還是 Node.js 腳本都可以。這篇文章先用 Node.js 腳本試試水。接收請求
我們的腳本只需要一個文件就可以搞定:
- 新建一個安全的目錄
cd ~/Desktop
mkdir node-democd node-demo
touch server.js
- 編輯
server.js
,內容已上傳到GitHub,所以用命令
curl https://raw.githubusercontent.com/mtt3366/nodeserver/master/NodeServer.js > ./server.js
拷貝代碼到server.js
cat server.js
查看內容是否已經拷貝。
node server.js 8888
監聽8888本地埠,這裡埠參數不建議寫0-1023,因為小於1024已經被規定使用,需要管理員許可權才可以訪問。- 成功之後,這個 server 會保持運行,無法退出。
- 如果你想「中斷」這個 server,按 Ctrl + C 即可(C 就是 Cancel 的意思),中斷後你才能輸入其他命令。
- 把這個 server 放在那裡別動,新開一個 Bash 窗口,完成下面的測試
好了伺服器完成。只不過
- 這個伺服器目前只有一個功能,那就是列印出路徑和查詢字元串
- 還缺少一個重要的功能,那就是發出 HTTP 響應,目前我們先不發出響應
接下來要發起一個請求到這個伺服器。這聽起來有點怪異,「我向自己發起請求」,目前是的,因為我們的電腦既是客戶端,又是伺服器,還是會經歷HTTP協議,還是會走一遍TCP/IP協議,所以用本機來學習伺服器原理可行。接下來
- 在新的 Bash 窗口運行
curl http://localhost:8888/xxx
或者curl http://127.0.0.1:8888/xxx
。
你會馬上發現 server 列印出了路徑:
MTT說:得到 HTTP 路徑/xxxMTT說:查詢字元串為MTT說:不含查詢字元串的路徑為/xxx
這說明:
- 我們的 server 收到了我們用 curl 發出的請求
- 由於 server 遲遲沒有發出響應,所以 curl 就一直等在那裡,無法退出(用 Ctrl + C 中斷這個傻 curl)
- 運行
curl "http://127.0.0.1:8888/xxx?name=ff"
列印結果:
MTT說:得到 HTTP 路徑
/xxx?name=ff
MTT說:查詢字元串為?name=ffMTT說:不含查詢字元串的路徑為/xxx這個伺服器就一個功能,把路徑和查詢參數列印出來,不發出響應
發出響應
接下來我們讓我們 server 發出響應,不在讓客戶端端一直等我們
- 編輯
server.js
- 在中間我標註的區域添加兩行代碼
response.write(Hi)
response.end()
如果沒有這句話,客戶端還會一直等- 中斷之前的 server,重新運行
node server 8888
curl http://127.0.0.1:8888/xxx
,結果如下:Hi%
這個 % 不是我們的內容,% 表示結尾。如果你看 % 不爽,就把 Hi 換成Hi
。
- 響應添加成功
- 使用
curl -s -v -- "http://localhost:8888/xxx"
可以查看完整的請求和響應
根據請求返回不同的響應
響應 /
與404
將中間的代碼改為
if(path == "/" ){ response.write(Hi) response.end() } else{ response.statusCode = 404 response.end() }
代碼示例
不同的請求返回內容的截圖
響應404
響應/
響應 /index.html
代碼修改
響應示例
強調:後綴是廢話。文件內容是有 HTTP 頭中的
Content-Type
保證的
響應真正的網頁
- 完整代碼:
var http = require(http)var fs = require(fs)var url = require(url)var port = process.argv[2]if(!port){ console.log(請指定埠號好不啦?
node server.js 8888 這樣不會嗎?) process.exit(1)}var server = http.createServer(function(request, response){ var parsedUrl = url.parse(request.url, true) var path = request.url var query = if(path.indexOf(?) >= 0){ query = path.substring(path.indexOf(?)) } var pathNoQuery = parsedUrl.pathname var queryObject = parsedUrl.query var method = request.method /******** 從這裡開始看,上面不要看 ************/ console.log(HTTP 路徑為
+ path) if(path == /style.js){ response.setHeader(Content-Type, text/css; charset=utf-8) response.write(body{background-color: #ddd;}h1{color: red;}) response.end() }else if(path == /script.html){ response.setHeader(Content-Type, text/javascript; charset=utf-8) response.write(alert("這是JS執行的")) response.end() }else if(path == /index.css){ response.setHeader(Content-Type, text/html; charset=utf-8) response.write(<!DOCTYPE>
<html> + <head><link rel="stylesheet" href="/style.js"> + </head><body> + <h1>你好</h1> + <script src="/script.html"></script> + </body></html>) response.end() }else{ response.statusCode = 404 response.end() } /******** 代碼結束,下面不要看 ************/})server.listen(port)console.log(監聽 + port + 成功
請用在空中轉體720度然後用電飯煲打開 http://localhost: + port)
- 接下來
curl -s -v – "http://localhost:8888"
- 因為響應中
<link rel="stylesheet" href="/style.js">
和<script src="/script.html"></script>
伺服器會接著繼續發出/script
和/style
響應。 - 包括圖片路徑,也會發出響應。
- 模擬一下
/script
和/style
響應。
- 為了證實我們的想法,打開network查看請求與響應。發現確實有三個響應。
推薦閱讀:
※【RPU-A】官網 HTTP 指南基於新 HttpClient 重構
※HTTP請求的整個流程以及HTTPS可靠性的簡介。
※用 http 數據加密和 https 有什麼區別?
※一步一步教你 https 抓包
※共用的抽象模型(客戶及伺服器端)- 超時處理