最熟悉的陌生人:API


Posted by ai86109 on 2020-07-07

前言

你可能常聽到 API 這個詞,甚至可能還會使用它,但要你對一個完全不懂的人解釋什麼是 API,可能就不太行了,說不定解釋到最後你自己也開始懷疑人生。

所以什麼是 API?

建議可以看這篇:從拉麵店的販賣機理解什麼是 API,我自己是看完這篇文章之後才恍然大悟。

先假設你已經看完這篇文章了,這邊再簡短的複習一下。

API, application programming interface(應用程式介面),簡單來說就是雙方需要交換資料時,就要透過 API。

就拿我們最常用的 USB 來說,他就是一個介面,製作隨身碟的廠商不用煩惱要怎麼符合所有電腦的規格,只要透過 USB 這個介面去製作就可以了,因為大家都是按照這個規格,所以按照某一個規格來進行資料交換的東西,就是可以稱為 API。

API 有很多種,與網路有關的稱為 Web API ,而透過 HTTP 的 API 稱為 HTTP API,通常做好設定之後,發送 request 就會回傳 response(也就是你要的資料)。

那另一個常聽到的 SDK 是什麼?

Software Development Kit(軟體開發套件),他和 API 不一樣的是,他已經幫你包裝好了,你可以直接用簡單的語法即可要到想要的資料。

簡單來說,Chrome 瀏覽器是 APP,那廣告封鎖器、LastPass 這些擴充功能,就是 SDK。如果天堂是 APP,那雄霸天堂就是 SDK。


串接一個簡單的 API

前面已經瞭解了 API 是什麼東西,這邊就要來簡單實作一下。

我們用一個測試用的網站,向他發送 request,試著得到他的 response。

這邊使用的 request 是要另外安裝的:https://www.npmjs.com/package/request

const request = require('request')

request(
    'https://reqres.in/api/users',
    function (error, response, body){
        console.log(body)
    }
)

會得到{"page":1,"per_page":6,"total":12,"total_pages”:2,.....

依照網站上的說明,我們在 users 後面加上數字,可以印出第幾筆資料,就像這樣。

const request = require('request')

request(
    'https://reqres.in/api/users/2',
    function (error, response, body){
        console.log(body)
    }
)

我們就會印出第二筆資料。

那有辦法在 terminal 上輸入指令指定要輸出第幾筆資料嗎?
我們可以用 Node.js 內建提供的 process

const request = require('request')
const process = require('process')

request(
    'https://reqres.in/api/users/' + process.argv[2],
    function (error, response, body){
        console.log(body)
    }
)

這邊的 process.argv[2] 是指在 terminal 輸出的第 2 個元素。node index.js 2(node 就是 0,index.js 就是 1,2 就是 2)

同理,也可以使用 post 等 method。

const request = require('request')

request.post(
  {
    uri: 'https://reqres.in/api/users',
    form: {
      name: 'derek',
      job: 'engineer'
    }
  },
    function (error, response, body){
        console.log(body)
    }
)

就可以傳資料過去,這就是一個簡單的 API 串接。


資料格式

成功串接 API 之後,接著就是要來處理資料了,畢竟使用 API 就是為了資料交換呀。

當我們發送或接收資料時,資料都會有一定格式。

  • 純文字、自定義
    最自由,可以定義你想要的文字
    例如:我在發送 response 時,如果都成功我就發送‘狀態:良好’
    但接收端也要寫相對應的程式碼去判定傳回來的 response。
    例如:
    if (response.body.indexOf(‘狀態:良好’) >=0 ){
    ……
    }
    
  • XML, eXtensible Markup Language
    這個格式長得很像 HTML,後面的 ML 就是這種標籤格式<id></id>
    像是這樣

    <?xml version="1.0"?>
    <rss xmlns:media="https://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/" version="2.0">
      <channel>
          <title>Crazy Videos</title>
          <!--<link>https://yoursite.com/channels/crazyvideos</link>-->
          <description>Footage of strange things around the world</description>
          <pubDate>Wed, 07 Mar 2018 10:17:13 +0800</pubDate>
    
  • JSON, JavaScript Object Notation
    因為他的格式是基於 JavaScript 來的,所以和 JS 相容性超好,且他不像 XML 需要有很多標籤,所以檔案也會比較小。

因此前面的小實作,便可以將其回傳的 JSON 格式轉為 object。

request(
    'https://reqres.in/api/users',
    function (error, response, body){
        const json = JSON.parse(body)
        console.log(json)
    }
)

會印出

{
    page: 1,
    per_page: 6,
    total: 12,
    total_pages: 2,
    data: [
        {
            id: 1,
            email: 'george.bluth@reqres.in',
            first_name: 'George',
            last_name: 'Bluth',
            avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg'
        },

同理,可以將 object 轉為 JSON

const obj = {
    name: 'derek',
    mobile: 0912345678
}

console.log(JSON.stringify(obj))

會印出 {"name":"derek","mobile":912345678}

這邊要記得,JSON 並非只能在 JS 使用,任何格式在任何程式語言都可以使用。


HTTP API

在前面我們實際串接一個簡易的 API:測試用的網站,我們便是使用它所提供的格式進行操作。

所以想當然耳,當串接的需求開始變大時,一些規範或協定就會相應而生,在 HTTP API 這一塊會有幾種常見的:

  • SOAP, Simple Object Access Protocol
    這是一個以 XML 格式進行的資料傳遞。
    格式可參考:https://www.soapui.org/ ,但使用時不太可能自己寫,所以還是會藉由 library的幫助:https://github.com/vpulim/node-soap ,但由於 JSON 的崛起,目前已經很少人使用了。

  • SOAP 以外的 HTTP API
    其實大部分我們看到的 API 就是這一類,透過 HTTP 基本的 method 來進行溝通。這邊就要來講到 RESTful 了。

RESTful是什麼?

RESTful 其實不是一種協定,他是一種風格。例如:

  • 新增使用者 POST /users
  • 刪除使用者 DELETE /users/:id
  • 查詢使用者 GET /users/:id
  • 更改使用者 PATCH /users/:id

按照他規範的處理 request 的這種 API,就稱為 RESTful 風格的 API。

這邊再接續看幾個 API 範例,先看 delete。

const request = require('request')

request.delete(
    'https://reqres.in/api/users/2',
    function (error, response, body){
        console.log(response.statusCode)
    }
)

因為刪完他不會回你東西,所以用 response.statusCode 查,印出 204 表示刪除成功。

另外還有 patch

const request = require('request')

request.patch(
{
    uri: 'https://reqres.in/api/users/2',
    form: {
        name: 'hihi',
    }
},
    function (error, response, body){
    console.log(response.statusCode)
        console.log(body)
    }
)

這邊會印出 200,表示成功更改,而印出 body 也會看到,的確成功把 name 改成 hihi。

這裡要知道,剛剛提到的 HTTP API 只是網路交換資料的一部份,還有很多其他的方式可以使用。


好用的基礎網路工具&指令

第一個是 curl,如果是 Mac osx 10.84 以上的版本,curl 是內建的可以直接使用。

那要怎麼使用呢?

在 terminal 輸入,curl https://github.com/aszx87410,意思就是你發一個 get 的 request 到這裡,他會回傳你 response。

那如果你想要下載這個網站變成一個 html 檔案,curl https://github.com/aszx87410 > gitHub.html,此時他就會幫你創一個 github.html 的檔案,並且將你剛剛得到的 response 放到裡面,open github.html 便可以看到已成功複製網站。

剛剛是取 body,那如果要取得 header 可以使用,
curl -I https://github.com/aszx87410

其他還有很多功能,要使用時可以 google 看格式如何,基本上任何網路的相關操作都可以用 curl 完成。

當然也可以用之前教的 Node.js + request 等語法去完成。


接著要講指令。

  • nslookup www.google.com,可以解析 domain 的 IP address。

  • ping www.google.com,看能不能連到對方主機,他會一直不斷送封包
    除非是自己網路壞掉,或對方網路掛掉,不然就會一直傳下去。

  • telnet 124.108.103.104 80,這是用來連到這個網站的 80 port,
    可以看這個 port 是否有開。

但 telnet 最廣為人知的應用就是 ptt。

ptt 這套系統就是基於 telnet 這個協定,telnet 預設他的 port 是 23,telnet ptt.cc 23,所以你不打任何 port 就會預設 23 port。


#API #RESTful #JSON #xml #curl







Related Posts

大數乘法

大數乘法

Day 109

Day 109

不要動!把表單交出來(1) - formData

不要動!把表單交出來(1) - formData


Comments