網路基礎
HTTP
本篇為 [NET101] 網路基礎概論(搭配 JS 實作練習) 這門課程的學習筆記。如有錯誤歡迎指正。
全名是 HyperText Transfer Protocol,中文翻作「 超文本傳輸協定」。
HTTP 是一套網路傳輸協定,為全球資訊網的資料通訊的基礎。也就是說,網頁前端和後端在溝通時,就是透過 HTTP 協定進行。
簡言之,協定就是一個「標準」。協定是為了讓彼此溝通而建立的規範,制定標準以統一格式,如此能夠進行規模化。
而透過協議溝通的兩端,通常可分為客戶端(Client)和伺服器端(Server)。
網頁上的資訊,其實就是由許多 request 跟 response 構成。且兩者內容均分成 header 與 body,分別帶著不同資訊:
我們可透過瀏覽器的開發者工具、或是 HTTP 抓包工具 Charles 來查看詳細資訊,過程大致如下:
全名是 Domain Name System,負責將域名轉換成 IP 位置。
補充:localhost 跟 127.0.0.1 是什麼?
localhost
:是一個域名,對應的的 IP 位址是 127.0.0.1127.0.0.1
是回送地址,指本地機,一般用來測試使用
Google 提供免費的 DNS 伺服器 8.8.8.8 和8.8.4.4,如此可透過搜尋引擎來蒐集大數據。
就是透過 DNS 把 Request URL(github.com) 轉換成實際 IP 位置(13.250.177.223)。
nslookup
指令在終端機輸入 nslookup '網址'
:可查詢 DNS 伺服器。有可能出現多個結果,代表對應到多個 server。
即使我們沒有瀏覽器,也能夠過其他方式發送 request 跟取得 response。
利用 Node.js 的一套 library:request - Simplified HTTP client,來模擬瀏覽器發送 request 的過程,步驟如下:
npm install request
node index.js
可拿到 responsenode index.js > github.html
導入程式碼,一樣能打開網頁什麼是 HTTP Method
?在 HTTP 1.1 協定中,定義了八種方法,來以不同方式操作指定的資源。詳細可參考 HTTP 請求方法- HTTP | MDN:
這是為了讓 Server 能夠清楚辨別 request 的目的。
常用的幾個動作分別為:GET / POST / PUT / DELETE,正好對應到資料庫基本操作 CRUD 增刪查改:
一般的 API 可能會長這樣:
若以 RESTful API 風格開發:
由此可見 RESTful 的寫法較一致,且語意化更好理解。透過把「動作」藏在 HTTP method 裡面,而有唯一的 URL(/users
)表示資源位置,藉此統一 API 接口。
如果用 HTML 來比喻,寫網頁時我們可以全部使用 div 標籤,但為了幫助理解,通常會使用 li、section、article 等具有語意的標籤,即可從結構看出內容的作用。
參考資料:API 是什麼? RESTful API 又是什麼? - Medium
當中又以 GET
和 POST
兩種,為最常使用的 HTTP 請求方法。兩者最直觀的區別是「資料傳遞方式」與「安全性」。
GET
:向指定的資源要求資料,類似於查詢操作。POST
:將要處理的資料提交給指定的資源,類似於更新操作。在最下方夾帶 request 資訊:
是 HTTP 用「3 位數字代碼」來表示回應狀態,通常以開頭的數字來進行區分。詳細可參考 HTTP狀態碼- 維基百科:
200 OK
:代表成功204 No Content
:伺服器成功處理了請求,沒有返回任何內容(例如發出 DELETE XXX 訊息,回傳 204 代表刪除成功)301 Moved Permanently
:資源「永久」移到新位置302 Found
:資源「暫時」移到其他位置400 Bad Request
:請求語法錯誤、資源太大、請求訊息無效等404 Not Found
:找不到資源500 Internal Server Error
:伺服器出錯。例如搶票時伺服器當機503 Service Unavailable
:由於臨時的伺服器維護或者過載,伺服器當前無法處理請求參考資料:
前面我們已經實作一個 Client 端,也就是利用 request 這個 library 來顯示出來。接下來我們要利用 Node.js 內建 library:http
來實作 Server 端:
server.js
,並輸入下列程式碼:執行 node server.js
:不會跑出任何東西。因為沒有 console.log
任何東西,所以是正常的。此時程式會一直執行到按 Crtl + C
才會退出,符合 server 端必須不斷運行來接收資訊。
在瀏覽器輸入網址 localhost:5000
會跑出下列畫面:
localhost:5000
:回應 welcomelocalhost:5000/hello
:回應 helloredirect
部分和 res.writeHead(404)
,就完成一個較完整的 Server 端:404 Not Found
:localhost:5000/redirect
,會在 Response Headers 會出現 'lidemy': 'good'
:302 Found
:'localhost:5000/redirect
,瀏覽器就會轉址到新位置:'Location': 'https://google.com'
:輸入網址 localhost:5000/redirect
就會直接連到 google.com
先前提到「從電腦發出 request 到 server」,在溝通訊息這段過程,其實需要經過非常多道手續。因此就有組織將網路標準化,將網路連接過程分成數個階層(layer),每個階層都有特別的獨立的功能。
分層的好處,是只要處理該層級的事情就好,因為每個階層的程式碼可以獨立撰寫,功能也不會相互干擾。
而著名的分層模型主要有兩種:
由於協定非常嚴謹,較偏向理論。
TCP/IP 是由 OSI 七層協定簡化而來,為目前網路通訊的基礎架構。以下為兩者之間的比較圖與常見的通訊協定:
參考資料:2.4 TCP/IP 的傳輸層相關封包與資料 - 鳥哥的Linux 私房菜
IP 的全名是 Internet Protocol,中文是「網際網路協定」。
可分為 IPv4、IPv6 這兩種協議,兩者最主要差異在於「IP 地址的不同」:
我們常聽到的 IP 地址,代表在網路上的地址。在網際網路上,每台電腦之間,是透過 IP 位址來通訊。當中又分為下列幾種類型:
理想情況下,是每一台電腦都有一個 IP 位址。固定的 IP 位址,適合架設網站,也因為不會變動,確保使用者能夠連上伺服器。例如:伺服主機、網路設備多使用固定 IP。
一般用戶大多是浮動 IP。浮動 IP 解決了「IP 不夠用」這個問題,因為每次連線的 IP 位址皆不同,也不會輕易被駭客攻擊。
只有在內網才能互相連接,外網找不到該地址,所以內網 IP 位址是可以重複的。但對外網而言,一定會有一個「固定 or 浮動」的 IP 位址。例如:公司使用內網溝通,藉由鎖 IP 位址,可提高安全性。
通常以
192.168
或10.0
開頭的,都是虛擬 IP。
參考資料:浮動 IP 與 固定 IP 有何不同?? 各有何優缺點??
在應用層當中,每台電腦主機 IP 位置(localhost),可能對應到不同應用程式。例如:HTTP、FTP、信件收發等服務。
而 Port 扮演網路通訊的端點,用來區分不同功能。如此即可辨認出,該連線要對應到哪個應用程式。
server.listen(5000)
:代表監聽 5000
這個 Port,輸入網址 localhost:5000
即可連到這個服務如果沒有輸入 Port,會有一些預設或常用值:
參考資料:[網路管理]常用 port 說明
傳輸層(Transport Layer)協定提供不同主機之間的資料傳輸及控制。根據不同需求,又分為「可靠的 TCP」和「速度較快的 UDP」兩種協定:
參考資料:
參考 Huli - 從傳紙條輕鬆學習基本網路概念,我們能夠透過傳紙條的例子,來試著理解網路通訊概念:
可參考 Huli - 從拉麵店的販賣機理解什麼是 API,或是這部影片:什麼是 API?來瞭解。
全名是 Application Programming Interface,中文是「應用程式介面」。簡言之,就是方便溝通、交換資料的管道。
API 是應用程式、裝置之間資料的交換,但不一定要透過網路才能有 API,例如:
以下為實際的運用例子:
透過 API 能夠達到省時、便利、營利等優點,因此我們也可以說,API 是一個「能讓生產者與消費者雙方溝通的介面」。
與先前「實做一個 Client 端發送 request」操作方式相同,是利用 library request 來模擬瀏覽器發送 request 的過程。
將範本中的 google 網址改成 https://reqres.in/api/users
在終端機輸入 node index.js
,即可獲得 Regres API 所提供的資訊:
這樣其實就完成了簡單的 API 串接!透過丟一個 request 到網站,我們能夠獲取想要的資訊。
而透過 request 文件,我們能找到不同的 request.METHOD()
,瞭解如何使用各種方法:
https://reqres.in/api/users/<userID>
/api/users/2
為例:方法一:直接將網址改成 https://reqres.in/api/users/2
方法二:使用 node.js 內建 library process
這個方法是利用 process.argv
達成帶入參數,我們可以先用 console.log
來查看 process.argv
是什麼:
會發現 process.argv
其實是一個陣列,利用 process.argv[2]
就可以拿到我們需要的參數:
輸入 node index.js 2
,就可獲得 id: 2
的使用者資料:
https://reqres.in/api/users/
成功新增使用者資料:
註:這裡的操作只是測試用,並不會真的新增資料到網站。
https://reqres.in/api/users/<userID>
回傳 204
,代表成功刪除使用者資料:
https://reqres.in/api/users/<userID>
成功修改使用者資料:
Base URL: https://lidemy-book-store.herokuapp.com
說明 | Method | path | 參數 | 範例 |
---|---|---|---|---|
獲取所有書籍 | GET | /restaurants | _limit:限制回傳資料數量 | /restaurant?_limit=6 |
獲取單一書籍 | GET | /restaurants/:id | 無 | /restaurant/12 |
刪除書籍 | DELETE | /restaurants/:id | 無 | 無 |
新增書籍 | POST | /restaurants | name: 書籍名稱 | 無 |
更改書籍 | PATCH | /restaurants/:id | name: 書籍名稱 | 無 |
在發出 request 時,我們其實能透過兩種方式來帶入資料:
實際例子可參考Twitch API v5 文件,同樣支援這兩種方法:
Client-ID: XXXXX
)https://api.twitch.tv/kraken/users/44322889?client_id=XXXXX
)因此在串接之前,必須先確認該 API 支援哪種方式來發出請求。
在 API 實戰中的 response 資料其實就是「JSON 格式字串」。在談到如何整理資訊之前,先來介紹常用的資料格式:
前後標籤
包起來。
<firstName>John</firstName>
key
值要用雙引號 "key"
包起來[array]
、{object}
等;但 value 值
不能放 functionJSON.prase(<JSON>)
:將 JSON 格式字串轉成物件JSON.stringify(<object>)
:將物件轉成 JSON 格式字串參考資料:
同樣以串接 Reqres API 為例。得到 response 就是「JSON 格式的字串」,但這種資料並不易閱讀,也無法直接使用。
因此使用內建函式 JSON.parse()
做處理,就會轉成「JS 物件」:
如此就可以「物件」方式來取出想要的資料:
反之,若想把「JS 物件」轉成「JSON 格式字串」,可以用: JSON.stringify(<object>)
curl
在 curl 官網下載,安裝方法可參考 Day14 - cURL 工具,即可在終端機使用。
curl 做法非常簡單,只要在終端機輸入指令就可支援發 HTTP request 、下載及上傳檔案的功能,基本格式為:
GET
方法以使用 curl 能夠發 request 到 google 首頁為例:
crul 'http://www.google.com'
:即可下載該網頁程式碼crul '網址' > google.html
:可將回傳值導向其他檔案參考資料: