Node基礎入門(三):數據交互

上一篇《Node基礎入門(二):模塊》

數據是以報文爲載體在瀏覽器與服務器之間傳輸的,報文(message)是網絡中交換與傳輸的數據單元,即站點一次性要發送的數據塊,它由三個部分組成:

  • 起始行:報文的第一行就是起始行。請求報文的起始行描述服務器應該執行的操作和HTTP的版本,響應報文的起始行承載了狀態信息和操作產生的結果數據;
  • 首部:起始行後面有零個或多個首部字段。每個首部字段都包含一個名值對,首部以一個空行結束;
  • 主體:空行之後就是可選的報文主體,其中包含了所有類型的數據。請求主體中包括了要發送給Web服務器的數據;響應主體中裝載了要返回給客戶端的數據。起始行和首部都是文本形式且都是結構化的,而主體則不同,主體中可以包含任意的二進制數據(比如圖片、視頻、音頻、軟件程序)。當然,主體中也可以包含文本。

下面分別用GET請求和POST請求實現一個登錄功能,先新建http文件夾,內部新建index.jslogin.html兩個文件。

一、GET請求

只能傳輸少量數據(<32K,通過報文頭傳輸)。

index.js

let http = require('http')

http.createServer((req, res) => {
  // 我們先打印一下req.url,看看是什麼
  console.log(req.url)
}).listen(8080)

login.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登錄</title>
</head>
<body>
<!--action:主機+端口+被訪頁面的名稱,method:get-->
<form action="http://localhost:8080/login" method="get">
  賬戶:<input type="text" name="username"><br>
  密碼:<input type="password" name="password"><br>
  <!--type爲submit,點擊後就會觸發上面的action-->
  <input type="submit" value="登錄">
</form>
</body>
</html>

雙擊login.html訪問該頁面,賬戶輸入zhangsan,密碼輸入123,點擊登錄,命令行打印:/login?username=zhangsan&password=123,說明GET請求下,表單數據通過報文頭傳輸。

url模塊

如何獲取問號後面字符串(即query)中的各項數據呢?如果通過字符串的split方法進行分割取值的話感覺很麻煩,有沒有更好的辦法?其實Node提供了一個url模塊,index.js引入url:

let http = require('http')
let url = require('url')

http.createServer((req, res) => {
  // 調用url的parse方法,傳入req.url
  console.log(url.parse(req.url))
}).listen(8080)

執行node index.jslogin.html頁面輸入內容點擊登錄後,命令行打印:

Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?username=zhangsan&password=123',
  query: 'username=zhangsan&password=123', // 注意query這一行
  pathname: '/login',
  path: '/login?username=zhangsan&password=123',
  href: '/login?username=zhangsan&password=123' }

index.js代碼做一個小改動:console.log(url.parse(req.url, true)),即在url.parse方法中添加一個參數true(表示將query字符串處理成對象形式),接着重複上面的步驟再執行一次,看命令行結果:

Url {
  ...
  query:
   [Object: null prototype] { username: 'zhangsan', password: '123' }, // 注意,這一行變了
  ...  
}

現在,可以獲取到我們需要的pathnamequery了(之後再去數據庫裏匹配數據,該部分類容省略)

let {pathname, query} = url.parse(req.url, true)
console.log(pathname, query)

執行之後打印:

/login [Object: null prototype] { username: 'zhangsan', password: '123' }

二、POST請求

既能接收數據,又能提交數據(<2G,通過報文體傳輸)。採用POST請求傳輸的數據可能很大,所以Node是讓這些數據分段傳輸的,服務器接收到多個數據片段後再拼接起來使用。

index.js:

let http = require('http')
// 將post的數據從字符串類型轉化爲我們需要的json類型
let querystring = require('querystring')

http.createServer((req, res) => {
  // Node提供的on方法表示事件監聽,'data'表示傳輸的每個數據片段,每傳輸一段就會執行一遍on('data')方法;
  // post請求發送的數據不僅侷限於字符串,還有圖片或文件,所以回調函數以buffer這種二進制格式作爲參數;
  // 因爲例子中傳輸的數據長度很小,只需一個片段,但是實際生產中片段很多,所以用數組result去承載所有的數據片段
  let result = []
  req.on('data', buffer => {
    console.log(buffer) // No.1
    console.log(buffer.toString()) // No.2
    result.push(buffer)
  })
  // on('end')方法監聽傳輸完成,利用Bufer提供的concat方法把所有零碎片段拼接起來
  req.on('end', () => {
    console.log(result) // No.3
    let data = Buffer.concat(result)
    console.log(data) // No.4
    console.log(data.toString()) // No.5
    console.log(querystring.parse(data.toString())) // No.6
  })
}).listen(8080)

login.html和上面的基本相同,只是將form標籤的method的值改爲post

啓動Node服務,登錄頁面輸入zhangsan123點擊登錄,命令行打印:

注:上面兩處爲buffer數據執行toString方法其實是不嚴謹的,對於簡單數據(字符串)還可以,但是對圖片和文件數據就沒意義了,所以僅作爲舉例說明。

下一篇《Node基礎入門(四):案例》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章