# 網路基礎概論 ─ 重點整理 ## 為什麼需要通訊協定(protocol)? 請先想像一下,不同國家的人一起坐在一場圓桌會議上,有些人說日文、有些人說英文、有些人說中文,大家雞同鴨講,無法順利溝通。這時候就可以使用一個語言,是大家都會的語言,這樣的語言就像是 protocol。 Protocol 就像是是一個格式化的標準,讓不同規格、不同語言、不同系統的系統或是平台,都能透過這樣的標準,進行資訊的流通及處理。 舉例來說,要瀏覽網站的話,要遵守網站的通訊協定,叫 http ( HyperText Transfer Protocol );而要傳輸檔案,則要遵循傳輸檔案用的 FTP ( File Transfer Protocol )。 ## HTTP ( 超文本傳輸協定 ) ### 概要 了解網站前,先要知道網站的資訊是如何傳送的。Client 端( ex:是瀏覽器)發送HTTP Request (包含 head 跟 body)請求給 Server 端,Server 端收到後再回傳 Response 回應(包含 head 跟 body)給 Client 端。[詳請可看此。](https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BCweb%E5%BE%8C%E7%AB%AF-1-%E4%BB%80%E9%BA%BC%E6%98%AFweb-server-83ee32bc7d3e) ### 如何詳細看到資訊傳送的流程 1. 按 F12 打開開發者工具。 2. 點擊 Network 標籤,即可看到所有瀏覽器發送的所有 Request 跟 Response ( html 標籤)。 3. Request 跟 Response 都要按照既定模式才可以傳送成功。 ### DNS Server ( Domain Name System ) 將 Domain Name 網域名稱(www.google.com)翻譯成 IP 位址。 在 terminal 上可以使用 `nslookup` 的指令,後面加上欲查詢 IP 位址的網域名稱,即可查詢 IP 位址。如果查詢結果是 no response from server 時,可以在 Terminal 上使用 `netsh winsock reset`,再重啟電腦一次,即可順利使用 `nslookup` 指令。 ### 瀏覽器只是幫助我們協作的程式 瀏覽器是協助我們發送 request ,接收 response 的程式。透過 node.js 的 library ─ [request](https://github.com/request/request) ( Simplified HTTP client ),也可以模擬瀏覽器發送 request,步驟如下: 1. 先在 terminal cd 到專案資料夾,並輸入 `npm install reqest`指令。 2. 下載後先新增一個 js 檔案,並在檔案內貼上官網提供的程式碼。這個動作是為了實作發送 request 。 當中的網域名稱可自由更換到自己欲實作的網頁網域。 ```javascript= const request = require('request'); request('http://www.google.com', function (error, response, body) { console.error('error:', error); // Print the error if one occurred console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received console.log('body:', body); // Print the HTML for the Google homepage. }); ``` 3. 執行`node index.js > index.html`,將 console.log 出來的 response 寫入 index.html 內。 4. 執行 `index.html`(打開此檔案),即可順利看到最後結果。 ### header 跟 body request 跟 response 內都有包含 header 跟body。 header 寫的是一些額外資訊, body 寫的是主要內容。 ### HTTP 請求方法 詳細更多可以參考 [MDN](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Methods)。 #### get 索取並顯示資訊。如顯示圖片或 html 及 css。 透過 dev tool 內可以看到 request URL。複製此 URL 並另開一個分頁去執行,所看到的畫面,就是 response。而這個背後程式所做的事情,就是瀏覽器發送了一個 get request 到這個 URL,並接收到了 response。 #### post 提交資料並請求伺服器處理。如輸入帳號密碼。 特別注意的是,get request 沒有 body, post 有。 #### put 更改並取代原先資料。 假設今天原訂單是雞腿飯 3,排骨飯 5,put 雞腿飯 2,那這樣最後的訂單會是雞腿飯 2,連排骨飯 5 都會不見。 #### patch 更改指定資料。 假設今天原訂單是雞腿飯 3,排骨飯 5,patch 雞腿飯 2,那這樣最後的訂單會是雞腿飯 2,排骨飯 5,排骨飯 5 會被保留下來。 #### delete 刪除資料。 #### option 回傳該 server 可支援的溝通方式。 ### HTTP 狀態碼 Status Code 1. **1XX ─ 1 開頭的狀態碼:你等等 (client 端需要做一些處理)**。 3. **2XX ─ 2 開頭的狀態碼:成功**。 200 OK 就是完全順利成功 204 No Content 就是成功但沒有回傳任何訊息(使用 delete 時)。 3. **3XX ─ 3 開頭的狀態碼:去其他地方(重新導向)**。 301 Moved Permanently :就是這個網域永久的被移到其他位置,下次再度使用 get 時,會直接導向另一個網域。 302 Found(Moved Temporarily):是暫時被移到其他位置,下次使用 get 時,一樣會導到此網域。 304 Not Modified:東西跟之前長一樣,可以從快取拿就好。 4. **4XX ─ 4 開頭的狀態碼:你慘了(client 端錯誤)**。 400 Bad Request:請求語法錯誤、或資源太大…等等。 401 Unauthorized:未認證,可能需要登入。 403 Forbidden:沒有權限。 404 Not Found:找不到資源。 408 Request Timeout : 請求超時。可再隨時提交一次請求且無須修改。 5. **5XX ─ 5 開頭的狀態碼:我慘了(server 端錯誤)**。 500 Internal Server Error:通用的伺服器出錯。(搶票時常見) 503 Service Unavailable:伺服器暫時無法處理。 更多請看[維基百科](https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81),想看有趣版可以[點此](https://noob.tw/http-status-code/)。 ### 實作 server 端 透過 node.js 內的 library ─ `http` 實作 server 端。 1. 新增一個 server.js 檔案,並輸入以下內容。 ```javascript= let http = require('http'); // 引用 library: http let server = http.createServer(handleRequest); function handleRequest(req, res) { console.log('request url: ', req.url); if (req.url === '/') { res.writeHead(200, { // 更改 response header 'info': 'index' }) res.write('content'); // 更改 response body res.end(); return; } if (req.url === '/redirect') { res.writeHead(301, { // 'Location': '/category' // 轉址到 /category 'Location': 'https://google.com' // 轉址到 google.com }); res.end(); return; } if (req.url === '/hello') { res.writeHead(200, { 'info':('hello') }) res.write('hello') res.end() return; } res.write(404); res.end(); return; } server.listen(5000); // 監聽 5000 這個 port ``` 2. 執行`node server.js` 指令(執行 server) 3. server 會不斷的執行直到按下 Ctrl + c 驗證是否可以傳到 client 端: 1. 打開瀏覽器的新分頁,並輸入 http://localhost:5000,應該會看到畫面上出現 content。 2. 輸入 http://localhost:5000/hello ,畫面會出現 hello。 3. 輸入 http://localhost:5000/redirect ,畫面會跳轉到 www.google.com 。 4. 隨意輸入 http://localhost:5000/djioejfo ,畫面會出現無法連上這個網站(404 not found)。 ## TCP / IP TCP / IP 是電腦網路通訊協定,分成四個層級( 應用層、傳送層、網路層、鏈結層 )。更詳細可參考[鳥哥的私房菜](http://linux.vbird.org/linux_server/0110network_basic.php)。 ![](https://i.imgur.com/ZSQxJCe.png) 圖片來源:鳥哥的私房菜 從這個協定當中可以看到 HTTP 協定〈應用層〉建立在 TCP 協定〈傳送層〉上,而 TCP 協定又建立在 IP 位址〈網路層〉上。 ### IP 地址( Internet Protocol ) IP 全名為 Internet Protocol,中文為「 網際網路協定 」。 協定也有分版本,分別是 IPv4(Internet Protocol version 4) 跟 IPv6(Internet Protocol version 6)。IPv6 可用的地址更多,解決主要 IPV4 不夠用的問題,兩者的地址也完全不同。更多差異請[看這](https://www.ithome.com.tw/tech/92046)。 IP 也有分成**固定 IP、虛擬 IP、浮動 IP**。 1. **固定 IP**:每一台電腦都有一個 IP 位置(理想狀態下),這 IP 位置是固定的,費用也較高。而基本上伺服器都跟公司企業是用固定 IP,這樣才能保證使用者可以連上伺服器,不會突然找不到。 2. **虛擬 IP**:大公司內常常會需要因為資安因素,以連上同一個類似數據機的電腦設定虛擬 IP,避免將資料帶離公司,或者是防止駭客入侵。這些虛擬 IP 只有在內網才可以互相連接,對外一律都是同一個 IP 位置(有可能是固定 IP 或浮動 IP)。詳見下圖。 ![](https://i.imgur.com/0hjSHuI.png) 圖片來源:Huli 課程內容 這樣改變位址的數據機我們稱為 NAT,底下會在更仔細的討論 。 3. **浮動 IP**:許多一般及家用戶都是浮動 IP,IP 位址會隨著每次連線而改變,好處是電信公司不需要直接給一個固定 IP,也因為浮動的 IP 位址不易受到駭客攻擊。 想要查詢自己對外的 IP 位址,可以使用「 myip 」作為關鍵字,許多網頁都有提供這樣的服務使用。 ### NAT > NAT,Network Address Translation,網路位址轉譯。 剛開始是為了解決 IPv4 位址不夠的的問題,而想出的一個過渡期解決辦法。目前主要的用途是有三: 1. 封包偽裝(IP masquerade) * 改變私有 IP(內部 IP)改變成真實 IP(外部 IP)再傳送到網際網路。也就是我們前面提到的功能。 * 讓其他人不知道內部到底有幾個伺服器及 IP 分配情形而增加網路安全性。 2. 封包過濾 * 可以攔截網際網路進入私有網路的封包,阻擋怪客(Cracker)的攻擊。 * 因上述,NAT 是最重要的防火牆成員,也是一種「封包過濾器(Packet filter)。 3. 負載平衡(Load Balance) * 通常使用在 web server,一般網頁可能同時會有很多人連線到伺服器,單一台主機(伺服器)沒有辦法負荷這麼多的連線請求,這時候就可以透過前面說的封包偽裝的特性,更改 IP 位址後發送到不同的主機,藉此減輕單一主機的負擔,同時增加網路安全性。 備註:其實有個東西叫做[負載平衡器](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1)(Load Balancer),是一個軟體程式,主要就是在負責 load balance,詳細可參考 [文章一](https://akuma1.pixnet.net/blog/post/168326978-%E5%A4%A7%E6%9E%B6%E6%A7%8B%E7%9A%84%E6%A6%82%E5%BF%B5%E8%88%87%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%EF%BC%8D%EF%BC%8D%EF%BC%88%E4%B8%89%EF%BC%89load-balance) 及 [文章二](https://wiki.mbalib.com/zh-tw/%E8%B4%9F%E8%BD%BD%E5%B9%B3%E8%A1%A1) [資料來源](https://www.stockfeel.com.tw/nat-%E4%BC%BA%E6%9C%8D%E5%99%A8%E6%98%AF%E4%BB%80%E9%BA%BC%EF%BC%9F%E5%A6%82%E4%BD%95%E9%81%8B%E7%94%A8%EF%BC%9F/) ### Port 連接埠( 端口 ) 為了區分並接收同個電腦( IP 位址 )的不同服務,所以就有了 Port 。 在剛剛的實作一個 server 端所輸入的`server.listen(5000);`,這邊的 5000 就是一個 port。 預設的 port 有 HTTP (80)、HTTPS (443)、FTP (21)。常見的測試值為 3000、4000、4001。 ### TCP 與 UDP TCP 與 UDP 都是傳送層中的兩個協議。 大部分的網路協定都是建立在 TCP 上,因為 TCP 較為可靠、會透過「**三次握手**」確保資料送達。 而 UDP 重點在於速度,在日常網路應用上像是視訊或是轉播時,重點在於傳送速度而不是傳送穩定,因為漏了一兩個封包其實對使用者並不會有明顯的影響。 **何謂三次握手**? > 三次握手又稱三路握手,全名為 threee-way handshake。簡單來說 client 端跟 server 端會通過三次的聯繫來確保資訊有確實傳達給對方。 ![](https://i.imgur.com/7WVAE4q.png) 圖片來源:由 原上傳者為中文維基百科的Huage.chen - Transferred from zh.wikipedia to Commons by Shizhao using CommonsHelper., CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=36967543 ### 總結 | 層級內容 | 層級用義 | 紙條故事 | | -------- | ------ | --------| | HTTP / FTP| 傳輸內容 | 紙條內容 | | TCP / UDP | 傳輸方式 | 三次確認 / 講求速度 | | IP | 傳輸地址 | 寄件人和收件人| | 實體層 | 實體傳輸 | 郵差 | ## Server 伺服器 這裡的伺服器**並非**指的是像 Apache(Web Server)、FTP Server 這類管理伺服器的軟體。 這裡的伺服器指的是執行上述各種伺服器管理軟體的主機,伺服器管理軟體可能還包含 DNS Server、Mail Server、Database Server 等。通常具備較高的計算能力、能夠提供給一個或多個使用者使用的電腦/主機。 ### 種類 伺服器常見有三個種類: 1. 虛擬空間 * 只有空間而已,沒有操控權 2. 虛擬主機 * 一台實體主機上面有很多虛擬主機,可以視為 cloud * 如果共用的實體主機壞了,可以自由且無痛遷移至另一個實體主機 * 需和其他虛擬主機共享 CPU 、記憶體等實體主機的硬體效能。 3. 實體主機 * 自己有一台完整的主機 * 主機壞了裡面的資料也會完全損毀,難以修復 ### 管理 常見管理的方式有兩種: 1. 遠端連線:一般較常見在 window 系統,可能會使用 Microsoft 為 Windows 10 所免費推出的遠端伺服器管理工具(Remote Server Administration Tools,RSAT),或者是其他第三方工具:像是 Team Viewer、VNC。 2. SSH * 全名為 Secure Shell Protocol,安全的殼程式協定,提供類似 telnet 但更安全的遠端連線。 * 透過 command line 介面直接連到遠端的主機下指令,通常是打 `ssh + ip位址` ,連線成功後可以使用 `top` 確認主機效能。 * 最常見、普遍的管理方式。 ## VPN > Virtual Private Network,虛擬私人網路。根據維基百科,VPN 是一種常用於連接中、大型企業或團體與團體間的私人網路的通訊方法。 它利用隧道協定(Tunneling Protocol)來達到傳送端認證、訊息保密與準確性等功能。 概念基本上就像是先連到一個主機,再由那個主機連線到其他地方。常見的應用: * 公司內網:先連到公司內網才能存取公司的資料。 * 使用學校服務:同理,連到學校內部才能使用學校資料 * 翻牆 ## API > 全名為 Application Programming Interface,中文翻譯為「應用程式介面」。簡單來說透過 API 就是一個交換資料的工具。 API 有分很多種,這邊會提到的是基於 HTTP 協定下的 Web API (HTTP API)。 API 常見的 CRUD 功能分別指的是:新增(Create)、讀取(Read)、更新(Update)、刪除(Delete),有時候會聽到五項功能,多了一個列表(List)。 ### 如何串接 API #### 方法一 有個簡單提供測試是否可以串接成功的 API 網站 ─ [Regres](https://reqres.in/)。透過此網站下方 jQuery 內提供的 URL,放入測試程式碼內,即可實測。 ```javascript= const request = require('request'); request('https://reqres.in/api/users', function (error, response, body) { console.log( body); // Print the HTML for the Google homepage. }); ``` 在 URL 後方也可以加上欲加入的物件,像是https://reqres.in/api/users/2, 即可呈現 ID :2 的元素。 若是想要在 Terminal 上直接執行 `node index.js 2` ,可以另外在檔案內加入`const process = require('process');`,並可以先用`console.log`測試 process 到底是甚麼。 在 terminal 上執行 `node index.js 2`,就會發現顯示出來的結果是。 ![](https://i.imgur.com/g5oHvad.jpg) 第一行顯示的結果表示,node 位置。 第二行顯示的結果表示,index.js 位置。 第三行顯示的結果表示,2。 process.argv[2] 作為一個陣列,欲取第三個元素。並將此放在 URL 後。範例碼如下: ```javascript= const request = require('request'); const process = require('process'); request( 'https://reqres.in/api/users/' + process.argv[2], function (error, response, body) { console.log(body); } ); ``` 這時候如果在 Terminal 內中執行 `node index.js 2`,即可順利顯示 ID 2 的內容,執行 `node index.js 3`,也可順利顯示 ID 3 的內容。 #### 方法二 透過之前有提到的 request library 的[ Github 網頁](https://github.com/request/request#forms),點選 forms,並使用之前所提到的[ reqres ](https://reqres.in/)將相關資料填入。 ```javascript= const request = require('request'); const process = require('process'); request.post( { url:"https://reqres.in/api/users", form: { name:'shelly', job: 'none' } }, function (error, response, body) { console.log(body); } ); ``` 執行 `node index.js ` 也可成功寫入資料(這邊只是測試用,所以並不會真正寫入資料)。 ### 實測串接 API 該如何實際執行 API 的 GET、POST、PATCH、DELETE...等指令呢?可以透過之前提到的[ request 官方文件](https://github.com/request/request),並 ctrl + F 找關鍵字「request.METHOD()」,找到如何使用的方法。 以下實作 DELETE 跟 PUT。 #### DELETE 依照官網在所提供的語法(`request.delete`),以下提供範本。 ```javascript= const request = require('request'); const process = require('process'); request.delete( "https://reqres.in/api/users/2", function (error, response, body) { const json = JSON.parse(body); console.log(json); } ); ``` 執行後會發現沒跑出任何 response。這時候我們可以在第六、七行之間加上`console.log('body:', body)`,確認 body 內容。執行後發現 body 是空的。 這時候我們可以再透過印出 status code 確認狀態。透過`console.log(response.statusCode)`回傳的結果是 204 。表示是成功的,只是沒有內容(因為已經刪除完畢)。 #### PATCH 與 POST 運用的格式相同,範例如下: ```javascript= const request = require('request'); const process = require('process'); request.patch( { url:'https://reqres.in/api/users', form: { Name:'Shell' } }, function (error, response, body) { console.log(body); } ); ``` ### RESTful API RESTful 是一種風格,該如何形容這個風格呢?就是一種語意化、更為嚴謹的描述 API 方式,目前也是最常見的方式。 ![](https://i.imgur.com/SYoumdT.jpg) 本圖片源自 Huli 上課教材。 在最左邊的一欄當中是要做的事情,左二是欲使用的指令,取而代之咖啡色字體的是 RESTful 風格的指令,右二是非 RESTful 風格的寫法,右一是 RESTful 風格的寫法。 所以可以看到 RESTful 的寫法較為一致、也更好理解。 [這篇簡報](https://github.com/TritonHo/slides/blob/master/Taipei%202016-04%20talk/RESTful%20API%20Design-tw-2.1.pdf)有更仔細地談甚麼是 RESTful API。 ## 資料格式 之前我們提到的發送或是回傳的資料,都是有格式的。這些在電腦科學中,資料格式是電腦中儲存、傳輸資料的方式。 資料格式可以簡略分成三種:純文字與自定義格式、XML、JSON。 ### 純文字與自定義格式 > 直接透過文字跟條件式定義格式。 ### XML > 全名是 Extensible Markup Language,中文是可延伸性標記式語言。XML 跟 HTML 一樣,都是屬於 Markup Language 標記式語言,均透過前後的標籤來包覆住內容。這裡可參考更多[ XML ](https://support.office.com/zh-tw/article/xml-%E5%85%A5%E9%96%80-a87d234d-4c2e-4409-9cbc-45e4eb857d44)入門文件。 以前傳輸資料經常使用 XML,現在多數人都使使用 JSON。 ### JSON > 全名是 JavaScript Object Notation ,中文是 JavaScript 物件表示法。依照維基百科,是一種輕量級的資料交換語言,該語言以易於讓人閱讀的文字為基礎,用來傳輸由屬性值或者序列性的值組成的資料物件。 雖然 JSON 稱之為 JavaScript 物件表示法,但是這個資料格式被廣泛的以函式庫的方式,用在其他語言當中。 JSON 所需要的儲存空間相較 XML 少上許多,所以**目前 JSON 是最普遍被使用的資料格式。** 在程式判讀上 XML 相較另一個資料格式 JSON 需要花費更多時間耗費資源。更多兩個資料格式的比較,可以看[ JSON與XML優缺點對比分析 ](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/276753/)。 #### 實作 JSON 之前實作 API 時所回傳的格式,就是 JSON 格式。 ```javascript= const request = require('request'); const process = require('process'); request( "https://reqres.in/api/users/2", function (error, response, body) { console.log(body); } ); ``` 回傳的 response 如以下: ```javascript= {"data":{"id":2,"email":"janet.weaver@reqres.in","first_name":"Janet","last_name":"Weaver","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"}} ``` 這個回傳的格式,就是一個 JSON 格式的 string。這樣的 String 比較難像物件一樣直接存取物件的 key 。那我們可以透過內建函式`JSON.parse()`,**將 string 改成物件格式。** 將上面的`console.log(body)`改成`console.log(JSON.parse(body))`。回傳的 response 則會變成以下: ```javascript= { data: { id: 2, email: 'janet.weaver@reqres.in', first_name: 'Janet', last_name: 'Weaver', avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg' } } ``` 那如果是物件格式想要改成 JSON 格式的 string ,可以使用 `JSON.stringify()`。 ## SOAP > SOAP 全名為 Simple Object Access Protocol ,中文是簡單物件存取協定。一種基於 XML 的交換資料協議規範。 目前已經很少人在使用,大多人都是使用 HTTP API,也就是我們上方所提到且實測的。 ## curl 指令 curl 指令操作簡單、在 terminal 就可以發送 request (需下載)。除了支援 HTTP request 之外,還可以上傳跟下載檔案。以下會簡單介紹幾種常用的 curl 指令,更多可以看[ TechBridge 的介紹文章](https://blog.techbridge.cc/2019/02/01/linux-curl-command-tutorial/)及另一篇[文章](http://blog.kent-chiu.com/2013/08/14/testing-rest-with-curl-command.html),寫得非常淺顯易懂。 ### 基本格式 `curl [options] [URL..]` ### GET `curl [URL]` * 發一個 GET 的 Request 到這個網址,執行後會收到 Response。 * 可以組合其他指令,像是使用 `curl [URL] > index.html`。就下載此 response 到 index.html 裡。 ### 取得 response 的 header 1. `curl -I [URL]` 2. `curl -- head [URL]` 這邊有一篇[文章](https://www.eebreakdown.com/2016/10/curl-http.html)非常簡單的說明了如何使用 curl 做 http 的測試。 ## 其他常用的 Command line 指令 ### Ping `ping [Url]` 測試後方放入的網址是否可順利連結上。 ### telnet `telnet [URL] [Port]` 查詢是否可以連接到指定的 port。 剛開始無法使用,參考了[這篇文章](https://www.namecheap.com/support/knowledgebase/article.aspx/9667/2194/what-are-traceroute-ping-telnet-and-nslookup-commands#telnet) ,解決了第一步無法使用。 經由 telnet 連到 IP 位址的 port 後,可以輸入「get/」就會取得 GET request 的資料。其它指令也是可以直接操作。 補充現狀:剛先透過 `nslookup` 查詢 google.com 的 IP 位址,再透過 `telnet` 查詢 port。但目前還是似乎無法使用 `telnet` 的指令,可使用的指令是 `telnet ptt.cc`。 ## 實際串接 TWITCH API 所遇到的問題 基本上按照串接 TWITCH API 的[教學文件](https://dev.twitch.tv/docs/api/)即可,但我還是遇到非常多的問題。這邊紀錄幾個非常耗費我耐心與腦力的問題,避免之後再犯: ![](https://i.imgur.com/TQSIv1n.png) 1. STEP 1 :註冊完 Twitch 帳戶後在這邊註冊應用程式,重新導向網址後還需要加上 port。 2. STEP 2 :在 terminal 輸入文件上的 sample code 時,要注意的地方有很多。 * `curl: (6) Could not resolve host:` 和 `curl: (1) Protocol "'https" not supported or disabled in libcurl`的問題解法:裡面的單引號('')全數都要換成雙引號("")。 * 文件內 sample code 的斜槓是讓你換行,但 cmder 無法同時執行兩行,需要手動把 / 刪除。 * Client-ID冒號後不可以有空格。 參考資料:[單引號換雙引號](https://stackoverflow.com/questions/6884669/curl-1-protocol-https-not-supported-or-disabled-in-libcurl) ## 實做 API 可參考保哥的[影片](https://www.youtube.com/watch?v=uFKa4xrc42c)。 ###### tags: `HTTP Request`、`API`