透過網路交換資料的方式(SOAP 和 RESTful API)


Posted by saffran on 2021-02-06

透過網路交換資料的第一種方式:SOAP

SOAP 簡介

SOAP 的全名是 Simple Object Access Protocol,是一個協定,定義了另一種跟 server 溝通的方式

SOAP 的資料交換(request, response)都是透過 XML 的格式

因為 XML 的格式寫起來比較麻煩,因此都會透過一套 Node.js 的 library 叫做 node-soap 讓我更方便地去寫 request

例如:
先建立一個 server,在 server 提供一個 function 叫做 myFunction

client 端連接到 server 後,就可以用 client.MyFunction() 直接呼叫這個 myFunction 函式,這個 function 就是「server 提供給我呼叫的 function」

注意!底層還是一樣是用 XML 在溝通(也就是說,myFunction 會使用 XML 的格式,帶入一些參數)

var soap = require('soap');
  var url = 'http://example.com/wsdl?wsdl';
  var args = {name: 'value'};
  soap.createClient(url, function(err, client) {
      client.MyFunction(args, function(err, result) {
          console.log(result);
      });
  });

透過網路交換資料的第二種方式:SOAP 以外的其他 HTTP API

什麼叫做「其他的」API?

HTTP API 主要分成兩類:

  • 第一類:SOAP
  • 第二類:SOAP 以外的 HTTP API(佔大多數)

「SOAP 以外的 HTTP API」交換資料的方式是:
發送 request 到一個 API 網址,然後就會回傳一個 JSON 格式的 response
例如:PokéAPIreqres

RESTful 到底是什麼?

RESTful 不是一個協定,它只是一種「風格」
(建議你遵循 RESTful 這種風格,但不強制)

RESTful 風格就是:希望你可以好好的去使用這些 HTTP 的 methods

沒有遵循 RESTful 的 API

下圖中的 endpoints (也就是最右邊那欄)就是“沒有遵循” RESTful 風格的

可以看到在上圖的 API,要「刪除使用者」的話,是使用 POST 發送 request 到 /delete_user 這個網址去

這裡你可能會疑問的是:刪除不是要用 DELETE 嗎?

要注意的是:
「刪除」用 DELETE,是一個「良好的習慣」,並不是一個「規範」

只要後端 server 有處理好這件事情,用 POST 一樣也可以模擬「刪除」的功能

因為後端 server 也有 /delete_user 這個網址,所以,就算我是使用 POST,後端也會知道「所有被送到 /delete_user 這個網址的 request 都是要“刪除使用者”的」,並不會跟「新增使用者的 POST」搞混

但是,「不遵循良好習慣」的壞處是:

壞處一:每個工程師都會有不同的命名方式

例如:
「新增使用者」這個功能,有人取名為 /new_user,另一個人取名為 /create_user,另一個人取名為 /create_new_user

壞處二:還是可能會造成混淆,因為用 POST 來刪除是「不具有語意的」

雖然說使用 POST 一樣也可以做到「刪除」的功能,但是「用 DELETE 來刪除」才是具有語意的作法

就像在寫 html 時,所有的標籤都可以用 <div>, <span> 來寫,但這樣是沒有語意的。應該要使用 <session>, <article> 這些有語意的標籤比較好

有遵循 RESTful 的 API

下圖中的 endpoints (也就是最右邊那欄)就是有遵循 RESTful 風格的

RESTful 針對「API 網址、HTTP 動詞(POST, GET, DELETE 這些)」都有一個建議的規範。只要有遵循 RESTful 風格,就可以被稱為是 RESTful API

  • 「新增」就用 POST
  • 「刪除」就用 DELETE
  • 主要的 API 網址會是一個「資源名稱」(會使用複數):/users
  • 「刪除、查詢、更改」某個特定的使用者:/users 後面加上 :id

例如:
reqres 就是一個 RESTful API

透過網路交換資料的第 n 種方式:跳脫 HTTP 的限制

自定義資料交換

其實,有很多 API 是沒有建立在 HTTP 之上的,而是建立在其他的 protocol 上,並使用不同的資料格式來交換資料

各種好用工具及指令

必學指令:curl

用 curl 下載 html 頁面

輸入指令 curl https://github.com/yuwensaf
意思就是:我要發一個 GET 的 request 到 https://github.com/yuwensaf 這個網址(我的 GitHub 頁面)去,因此,得到的 response 就會是這個網頁的 html 程式碼

使用指令 curl https://github.com/yuwensaf > myGithub.html 可以把這個 response 導向到一個新的檔案(myGithub.html),這樣我就成功地把我的 GitHub 頁面下載下來了

打開 myGithub.html,就可以看到我的 GitHub 頁面

用 curl 取得網頁的 Header 內容

加上參數 -I,意思是:我只要 Header,我不要 Body

因此,輸入指令 curl -I https://github.com/yuwensaf 就可以看到 https://github.com/yuwensaf 這個網頁的 Header 內容了

用 curl 來 POST JSON 格式的資料

參考資源 How do I POST JSON data with cURL?

用 curl 來 POST JSON 格式的資料,寫法是這樣:
這裡的 \ 是「換行」的意思

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"username":"xyz","password":"xyz"}' \
  http://localhost:3000/api/login

拿之前講過的 reqres API 自己改一下:

curl --header "Content-Type: application/json" \
--request POST \
--data '{"name":"Romeo","job":"farmer"}' \
https://reqres.in/api/users

意思就是:
https://reqres.in/api/users 這個網址發一個 POST 的 request,是 JSON 格式的 request:{"name":"Romeo","job":"farmer"}

執行指令後就可以看到回傳的 response,代表我成功建立了一個 Romeo 這個新的 user:

{"name":"Romeo","job":"farmer","id":"887","createdAt":"2020-07-24T13:46:55.365Z"}%

ping, telnet 與 nslookup

nslookup

使用指令 nslookup github.com,就會回傳 github.com 這個 domain 的 IP 地址

ping

使用指令 ping google.com,就會一直丟封包到 google.com,藉此來測試自己是否可以連到 google.com 這台 server(是一個測試的步驟)

如果出現錯誤,那就代表有一方的網路壞掉了

按下 ctrl+C 可以結束指令

telnet 用途一

telnet 有很多用途,最簡單的用途就是:去 ping 一個指定的 port(連到一個指定的 port)
例如:
我用 nslookup github.com 查詢到 github.com 的 IP 地址是 140.82.112.4,我想要針對它的 80 port 去做 telnet(80 是 HTTP 的 port)

就可以輸入指令 telnet 140.82.113.4 80,意思就是:我要連到 140.82.113.4 的 80 port

結果回傳「Connected...」就代表:140.82.113.4 的 80 port 是有打開的

如果等很久都沒有回傳「Connected…」 ,就代表那個 port 沒有開

telnet 用途二

輸入指令 telnet 140.82.113.4 80 後,可以打一些字(傳資料給 github.com)

因為 github.com 是一個 HTTP 的 server,所以可以使用 GET 這個 HTTP method 來取得這個網頁的 html 程式碼

寫法如下:

參考資料 Telnet – Send GET/HEAD HTTP Request

telnet [SERVER] [PORT]
Trying xxx.xxx.xxx.xxx...
Connected to [SERVER].
Escape character is '^]'.
GET [WEB PAGE] HTTP/1.1
HOST: [SERVER]
<Press ENTER>

所以我輸入的指令是:

telnet 140.82.114.3 80                                   
Trying 140.82.114.3...
Connected to lb-140-82-114-3-iad.github.com.
Escape character is '^]'.
GET / HTTP/1.1
HOST: github.com

但是就只有回傳這樣:

HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://github.com/

說明:
回傳 301 Moved Permanently 就是轉址的意思,所以它叫你去找 https://github.com/
但用 telnet 應該是沒辦法直接連 https,因為有些憑證相關的東西要處理

telnet 用途三

輸入指令 telnet ptt.cc,意思就是:我要連到 ptt.cc 的 23 port

ptt 這套系統就是基於 telnet 協定

telnet 預設給 ppt 的 port 是 23,因此沒有輸入 port 也可以,telnet ptt.cc 預設就會是 telnet ptt.cc 23

網路的本質

網路的本質就是為了要「溝通」

因為希望溝通可以被「規模化」,因此就需要訂定一些「協定」讓大家去遵循這些標準

而身為網路相關的工程師,就必須去了解這些協定


#Network







Related Posts

JavaSctipt 與瀏覽器的溝通

JavaSctipt 與瀏覽器的溝通

[心得] 統計,改變了世界

[心得] 統計,改變了世界

[ 筆記 ] 瀏覽器資料儲存 - Cookie、LocalStorage、SessionStorage

[ 筆記 ] 瀏覽器資料儲存 - Cookie、LocalStorage、SessionStorage


Comments