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-demo

cd node-demo

  • touch server.js
  • 編輯 server.js,內容已上傳到GitHub,所以用命令

curl raw.githubusercontent.com > ./server.js

拷貝代碼到server.js

  • cat server.js查看內容是否已經拷貝。

  • node server.js 8888 監聽8888本地埠,這裡埠參數不建議寫0-1023,因為小於1024已經被規定使用,需要管理員許可權才可以訪問。
  • 成功之後,這個 server 會保持運行,無法退出。
  • 如果你想「中斷」這個 server,按 Ctrl + C 即可(C 就是 Cancel 的意思),中斷後你才能輸入其他命令。
  • 把這個 server 放在那裡別動,新開一個 Bash 窗口,完成下面的測試

好了伺服器完成。只不過

  1. 這個伺服器目前只有一個功能,那就是列印出路徑查詢字元串
  2. 還缺少一個重要的功能,那就是發出 HTTP 響應,目前我們先不發出響應

接下來要發起一個請求到這個伺服器。這聽起來有點怪異,「我向自己發起請求」,目前是的,因為我們的電腦既是客戶端,又是伺服器,還是會經歷HTTP協議,還是會走一遍TCP/IP協議,所以用本機來學習伺服器原理可行。接下來

  • 在新的 Bash 窗口運行 curl http://localhost:8888/xxx 或者 curl http://127.0.0.1:8888/xxx

你會馬上發現 server 列印出了路徑:

MTT說:得到 HTTP 路徑/xxxMTT說:查詢字元串為MTT說:不含查詢字元串的路徑為/xxx

這說明:

  1. 我們的 server 收到了我們用 curl 發出的請求
  2. 由於 server 遲遲沒有發出響應,所以 curl 就一直等在那裡,無法退出(用 Ctrl + C 中斷這個傻 curl)
  3. 運行curl "http://127.0.0.1:8888/xxx?name=ff"

    列印結果:

MTT說:得到 HTTP 路徑

/xxx?name=ff

MTT說:查詢字元串為

?name=ff

MTT說:不含查詢字元串的路徑為

/xxx

這個伺服器就一個功能,把路徑和查詢參數列印出來,不發出響應

發出響應


接下來我們讓我們 server 發出響應,不在讓客戶端端一直等我們

  1. 編輯 server.js
  2. 在中間我標註的區域添加兩行代碼
  3. response.write(Hi)
  4. response.end() 如果沒有這句話,客戶端還會一直等
  5. 中斷之前的 server,重新運行 node server 8888
  6. curl http://127.0.0.1:8888/xxx,結果如下:
  7. Hi%

    這個 % 不是我們的內容,% 表示結尾。如果你看 % 不爽,就把 Hi 換成 Hi
  8. 響應添加成功
  9. 使用 curl -s -v -- "http://localhost:8888/xxx" 可以查看完整的請求和響應

根據請求返回不同的響應


響應 /404

將中間的代碼改為

ifpath == "/" { 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 抓包
共用的抽象模型(客戶及伺服器端)- 超時處理

TAG:伺服器 | HTTP | 前端開發 |