# 五之 1 、API HW
###### tags: `NET101` `2020八月第二週` `進度筆記` `Lidemy心得` 8/15
基於 API 文件 來呼叫 API , 寫寫看。
---

---
## HW1 寫程式來呼叫 API 前十本書和書名。
- Base URL: https://lidemy-book-store.herokuapp.com
- 閱讀開頭給的 [API 文件](https://github.com/request/request#custom-http-headers) 並串接,用 node.js 寫出一個程式,執行後會在 console 列出前十本書籍的 id 以及書名。
- 輸出範例:
```
node hw1.js1 克雷的橋
2 當我想你時,全世界都救不了我
3 我殺的人與殺我的人
....
```
知道怎麼在網址後面接上 `books` 和 `limit` 就好辦多了~
根據提示完整的 API 位址就能列出來。
```
/* eslint-disable */ // 在該檔案關閉 ESLint
const request = require('request');
request(`https://lidemy-book-store.herokuapp.com/books?_limit=10`,
(error, response, body) => {
if (error) {
return console.log('抓取失敗', err);
}
let data
try {
data = JSON.parse(body);
} catch(error) {
console.log(error);
return
}
for (let i = 0; i < data.length; i += 1) {
console.log(`${data[i].id} ${data[i].name}`);
}
})
```
---
## HW2 串更多 API 。
請你閱讀開頭給的 API 文件並串接,用 node.js 寫出一個程式並接受參數,輸出相對應的結果,範例如下:
```
node hw2.js list // 印出前二十本書的 id 與書名
node hw2.js read 1 // 輸出 id 為 1 的書籍
node hw2.js delete 1 // 刪除 id 為 1 的書籍
node hw2.js create "I love coding" // 新增一本名為 I love coding 的書
node hw2.js update 1 "new name" // 更新 id 為 1 的書名為 new name
```
這個用到 ``.argv()`` 就比較小複雜,要用判斷式和 ``if...else...`` 或是 `switch` 來進行條件變換:
```
/* eslint-disable */ // 在該檔案關閉 ESLint
const request = require('request');
const args = process.argv;
const apiUrl = 'https://lidemy-book-store.herokuapp.com';
const action = process.argv[2]
const params = process.argv[3]
switch (action) {
case 'list':
listBooks();
break;
case 'read':
readBooks(params);
break;
case 'delete':
deleteBooks(params);
break;
case 'create':
createBooks(params);
break;
case 'update':
updateBooks(params, process.argv[4]);
break;
default:
console.log('Available commands: list, read, delete, create and update');
}
function listBooks() {
request(`${apiUrl}/books?_limit=20`, (error, res, body) => {
if (error) {
return console.log('抓取失敗', error);
}
const data = JSON.parse(body)
for (let i = 0; i < data.length; i += 1) {
console.log(`${data[i].id}. ${data[i].name}`);
}
});
}
function readBooks(id) {
request(`${apiUrl}/books/${id}`, (error, res, body) => {
if (error) {
return console.log('抓取失敗', error)
}
const data = JSON.parse(body)
return console.log(data.id + '.', data.name)
});
}
function deleteBooks(id) {
request.delete(`${apiUrl}/books/${id}`, (error) => {
if (error) return console.log('刪除失敗');
return console.log('刪除成功');
});
}
function createBooks(name) {
request.post({url: `${apiUrl}/books`, form: {name,}}, (error) => {
if (error) return console.log('新增失敗', error);
return console.log('新增成功')
});
}
function updateBooks(id, name) {
request.patch({
url: `${apiUrl}/books/${id}`,
form: {
name
}
}, (error, res) => {
if (error) {
return console.log('更新失敗', error);
}
return console.log('更新成功!?');
});
}
```
參考了解答和 [同學的筆記](https://hackmd.io/PhfjuTVzQPaiXYMiJ3F4qQ) , 整理得真的很漂亮 !
同時看到了 [Swift 起步走](https://itisjoe.gitbooks.io/swiftgo/content/apps/taipeitravel/intro.html) 。
---
## HW 3 找現成 API , 看懂這個 API 和回傳。
主要是使用這個 [佛心 API ](https://restcountries.eu/#api-endpoints-name) 。
這個程式很簡單,只要輸入國家的英文名字,就能夠查詢符合的國家的資訊,會輸出以下幾項:
```
國家名稱
首都
使用的貨幣名稱
電話國碼
```
輸出範例如下:
```
node hw3.js tai
============
國家:Taiwan
首都:Taipei
貨幣:TWD
國碼:886
============
國家:United Kingdom of Great Britain and Northern Ireland
首都:London
貨幣:GBP
國碼:44
============
國家:Lao People's Democratic Republic
首都:Vientiane
貨幣:LAK
國碼:856
```
用到之前學的 process.argv() 命令行參數來實戰,需要在 node xxx檔名.js + 名稱,例如:
- `node index.js Taiwan` 就會跑出 Taiwan 的名稱、資訊...等等。
- 觀察了一下,需要用到結果傳入迴圈來執行 。
- 同時運用到狀態代碼,並輸出結果。
```
const request = require('request');
const args = process.argv;
const API_ENDPOINT = 'https://restcountries.eu/rest/v2';
const name = args[2];
if (!name) {
return console.log('請輸入國家名稱');
}
request(`${API_ENDPOINT}/name/${name}`, (err, res, body) => {
if (err) {
return console.log('抓取失敗', err);
}
const data = JSON.parse(body);
if (data.status === 404) {
return console.log('找不到國家資訊')
}
for (let i = 0; i < data.length; i++) {
console.log('============')
console.log('國家:' + data[i].name);
console.log('首都:' + data[i].capital);
console.log('貨幣:' + data[i].currencies[0].code);
console.log('國碼:' + data[i].callingCodes[0]);
}
})
```
## HW4 從 [Twitch_V5 API](https://dev.twitch.tv/docs/v5) 文件中來看如何串 API (備註:這是舊版)。
```
- 1. 先執行兩部驗證,過程很繁瑣,主要是要在 Twitch , Account Settings => Security and Privacy => Two-Factor Authentication 給啟用。
- 2. 接著回 https://dev.twitch.tv/console 設定 Applications , Name 隨意但不能跟他人重複 , 然而用這組 http://localhost 在 URL 設定上會出問題,參照 http://localhost:8000/ 這組才能執行。
- 3. 註冊好後,去按下 Manage Application => 就可以看到 Client ID , 並且如何用註冊的 Client ID 來玩和加入 request header 就很有趣。
```
```
const request = require('request');
const options = {
url: 'https://api.twitch.tv/helix/games/top',
headers: {
'Client-ID': 'You can't see this ID,
'Accept': 'application/vnd.twitchtv.v5+json'
},
};function callback(error, response, body) {
if (!error && response.statusCode === 200) {
const info = JSON.parse(body);
for (let i = 0; i < info.data.length; i += 1) {
console.log(info.data[i].id, info.data[i].name);
}
}
}request(options, callback);
```
---
HW4 參考資料:
[Configuring Onion Services for Tor](https://2019.www.torproject.org/docs/tor-onion-service.html.en)
[關於OAuth 2.0-以Facebook為例](https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BCoauth-2-0-%E4%BB%A5facebook%E7%82%BA%E4%BE%8B-6f78a4a55f52)
[Twitch streams API 串接實例](https://chriskang028.wordpress.com/2017/07/29/twitch-streams-api-%E4%B8%B2%E6%8E%A5%E5%AF%A6%E4%BE%8B/)
[OAuth 2.0 筆記 (4.2) Implicit Grant Flow 細節](https://blog.yorkxin.org/2013/09/30/oauth2-4-2-implicit-grant-flow.html)
[10分鐘理解OAuth和facebook登入原理](https://gigenchang.wordpress.com/2014/01/26/10%E5%88%86%E9%90%98%E7%90%86%E8%A7%A3oauth%E5%92%8Cfacebook%E7%99%BB%E5%85%A5%E5%8E%9F%E7%90%86/)
[暗網架站首部曲-Tor](https://pincong.rocks/article/699)
[Getting Started with the Twitch API](https://dev.twitch.tv/docs/api/)
[Invalid redirect URI on spotify auth](https://stackoverflow.com/questions/32956443/invalid-redirect-uri-on-spotify-auth)
[Twitch API 串接(一)申請用戶端ID及尋找所需API](https://medium.com/@winny3531/twitch-api-%E4%B8%B2%E6%8E%A5-%E4%B8%80-%E7%94%B3%E8%AB%8B%E7%94%A8%E6%88%B6%E7%AB%AFid%E5%8F%8A%E5%B0%8B%E6%89%BE%E6%89%80%E9%9C%80api-ef4d562fe9b0)
[ 第十七天:怎麼讓別人連到我作好的網站? ](https://ithelp.ithome.com.tw/articles/10195920)
---
## HW5 簡答題
-----------------------------------------------------------------------------------------------------------------------------------------
## 1.請以自己的話解釋 API 是什麼?
__應用程式介面 (Application Programming Interface) , a.k.a. API 。__
- 介面很重要,透過介面來溝通。
- 電腦要透過介面存取和溝通。
因此可以分為使用 API 和提供 API:
- 不希望直接被存取資料庫。
- 定義那些資料要被存取。
- 例如: 作業系統提供 API、檔案透過 API 讀取。
- 串接 API = 拿取資料。
- 提供 API 給他人來網站存取資料或是新增資料。
__重點: 透過 API 即可讓雙方交換資料。__
-----------------------------------------------------------------------------------------------------------------------------------------
## 2.請找出三個課程沒教的 HTTP status code 並簡單介紹。
參考了 [MDN 技術手冊 - HTTP 狀態代碼](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Status) 還有 [HTTP 狀態碼 (Status Codes)](https://notfalse.net/48/http-status-codes):
### 205 重設內容 (reset content)
- 伺服器接受請求,並且 User 的代理端應重新設置內容。
- 像是 User 送出表單,結果收到 205 的情況代表瀏覽器希望把表單內容清空。
- 大概是方便接下來提交新的表單或是美觀要求。
### 206 部分內容 (partial content )
- 會產生此狀態是因 User 端送出的範圍標頭 (range header) 將造成下載分流。
- 將動作 GET 用在範圍請求的情況,像是使 Server 傳輸大型文件的單個頁面。
### 207 多個狀態 (multi-status, WebDAV)
- 需要多個狀態代碼才能響應傳達有關多種資源的資訊。
- 用於多個獨立操作來提供不同狀態。
-----------------------------------------------------------------------------------------------------------------------------------------
## 3.假設你現在是個餐廳平台,需要提供 API 給別人串接並提供基本的 CRUD 功能,包括:回傳所有餐廳資料、回傳單一餐廳資料、刪除餐廳、新增餐廳、更改餐廳,你的 API 會長什麼樣子?請提供一份 API 文件。 。
```
http://www.měishí píngtái.com/
"food_restaurant" [
{
"id": "1",
"food_restaurant_name": "Tamsui_A-gei",
"food_restaurant_classification": "street_food",
"food_restaurant_address": "Zhenli street., Tamsui Dist., New Taipei City",
},
{
"id": "2",
"food_restaurant_name": "TNT",
"food_restaurant_classification": "western_food",
"food_restaurant_address": "Zhongzheng E. Rd., Tamsui Dist., New Taipei City",
},
{
"id": "3",
"food_restaurant_name": "Red Castle",
"food_restaurant_classification": "chinese_food",
"food_restaurant_address": "Sanmin St., Tamsui Dist., Taipei City",
},
{
"id": "4",
"food_restaurant_name": "Shenghong Teppanyaki",
"food_restaurant_classification": "taiwanese_teppanyaki",
"food_restaurant_address": "Beixin Rd., Tamsui Dist., Taipei City",
},
{
"id": "5",
"food_restaurant_name": "Hi-Lai-FOODS",
"food_restaurant_classification": "all_you_can_eat",
"food_restaurant_address": "Zhongshan N. Rd., Shilin Dist., Taipei City",
},
],```| 說明 | Method | path | 參數 | 範例 |
|--------|--------|------------|----------------------|----------------|
| 獲取所有餐廳 | GET | /food_restaurant | _limit:限制回傳資料數量 | /food_restaurant?_limit=5 |
| 獲取單一餐廳 | GET | /food_restaurant | :id | /food_restaurant/:id |
| 新增餐廳 | POST | /food_restaurant | 餐廳名稱 | :add |
| 刪除餐廳 | DELETE | /food_restaurant | 無 | 無 |
| 更改餐廳資訊 | PATCH | /food_restaurant | 變更的項目: 內容 | 無 |
```
GET http://www.měishí píngtái.com/food_restaurant/:id
獲取其中一個餐廳時: GET /food_restaurant/:id
```
```
GET http://www.měishí píngtái.com/food_restaurant/:add
新增餐廳:POST /food_restaurant/:add
```
```
POST http://www.měishí píngtái.com/food_restaurant/:id
更替餐廳:DELETE /food_restaurant/:id
```
```
DELETE http://www.měishí píngtái.com/food_restaurant/:del
刪除餐廳資訊:PATCH food_restaurant/:del
```
```
PATCH http://www.měishí píngtái.com/food_restaurant/:alt
修改餐廳資訊:PATCH food_restaurant/:alt
```
-----------------------------------------------------------------------------------------------------------------------------------------