Tag(網路基礎)
Tag(API)
參考資料 輕鬆理解 Ajax 與跨來源請求
就像是自動販賣機的按鈕/面版
可口可樂公司的商品中有各類可樂飲料
1.今天你想取得一瓶原味可樂
2.只要單純的按下面版上原味可樂的 按鈕
3.接著你就可以在取物口拿到一瓶可樂
上面第二個動作中的面版/按鈕, 就是所謂的 API 了
透過這個面版, 你可以拿到可口可樂公司的飲料
過程大概就是:
- 想要一瓶可樂(想要的資料)
- 按下按鈕(送出資料需求)
- 拿到飲料(取得資料)
參考資料 什麼是API?
參考資料 從拉麵店的販賣機理解什麼是 API
全名為 Application Programming Interface,中文翻譯為「應用程式介面」
簡單來說就是方便溝通、交換資料的管道。
API 有分很多種:
* 軟硬體廠商的 API
* 有作業系統用的 API ,用於傳輸、寫入、讀取資料…等等電腦上一切的操作
* 自己團隊內部用的 API
* 對於網頁來說就是 Web API
是基於 http 協定下運作的 API
參考資料 JSON 格式與 JavaScript 解析教學範例
JSON 檔案具備了鍵(Key)
與值(Value)
JSON 字串
可以包含 object (物件) 或 array (陣列) 資料
{
"number": "1020501",
"name": "小傑",
"age": 32,
"sex": "M",
"interest": [
"網頁設計",
"撰寫文章"
]
}
串接API的本質就是交換資料
參考資料 JSON 格式與 JavaScript 解析教學範例
JavaScript物件
{name: 'Renee',isTall: true}
JSON 格式的字串
物件的屬性名name,在JSON中被引號包起來變成'name',也就是說原本的屬性名到了JSON變成字串
{'name':'Jen','isTall':'true'}
JavaScript物件 & JSON 格式的字串 一起印出來比對
物件與JSON字串的轉換,有兩個重要函式
JSON.stringify()
可以 將 JavaScript
物件序列化成 JSON
字串
第二個參數 可以是 是一個 function 或是 一個 array
第三個參數,來控制結果字串的縮排間距,並會自動換行
// JavaScript 物件
var member = {
"number": "1020501",
"name": "小傑",
"age": 32,
"sex": "M",
"interest": [
"網頁設計",
"撰寫文章"
]
};
// 使用第二個參數 function 方式,排除 age 特性不被序列為 JSON 字串
console.log(
JSON.stringify(member, function(key, value) {
if (key === "age") return undefined;
return value;
})
);
JSON.parse()
方法可以將 JSON
字串 解析成 JavaScript
物件 ,這樣就可使用 JavaScript
進行操作了
第二個參數 function 用來轉換解析出的屬性值,return 的值決定最後在物件上的特性值
// 宣告字串須使用 `` 包起來
var jsonString = `{
"number": "1020501",
"name": "小傑",
"age": 32,
"sex": "M",
"interest": [
"網頁設計",
"撰寫文章"
]
}`;
// 使用第二個參數 function 方式,排除 age 特性不被包括在物件
var member = JSON.parse(jsonString, function(key, value) {
if (key === "age") return undefined;
return value;
});
// 取得物件
console.log(member);
參考資料 Proper way to catch exception from JSON.parse
參考資料 The 80/20 Guide to JSON.stringify in JavaScript
參考資料 JSON.parse() and JSON.stringify()
try…catch 語法使用
可以在程式執行可能拋出錯誤的地方使用,主動捕捉並處理錯誤,避免整個程式因為發生錯誤而停止執行。
try {
// 預期可能會發生錯誤的程式碼
} catch (e) {
// try 區塊有拋出錯誤時,則執行這裡的程式碼
} finally {
// finally 區塊的程式碼一定會在最後被執行
// 可以省略 finally 區塊
}
function validateData(jsonData){
let data
try{
data = JSON.parse(jsonData);
} catch(e) {
console.log('Error data', e)
data = null
}
return data
}
console.log(validateData('[1, 5, "false"]'))
console.log(validateData('1, 11')) //null
參考資料 談談 JavaScript 中的錯誤處理 Error Handling
參考資料 錯誤與例外處理
API 文件通常都不會給出完整網址,因為絕大多數 API 其實都是透過兩個部分所組成
範例1 串接API,執行後會列出前十本書籍的 id 以及書名
參考資料 30 天 Javascript 從入門到進階:物件
參考資料 JavaScript Template String 樣板字串
參考資料 正確配置 Visual Studio Code 開發和除錯 TypeScript
Base URL
: https://lidemy-book-store.herokuapp.com
學習看request文件
// 引入了request的library
const request = require('request');
// 抓取 url 的內容
request.get({
url: 'https://lidemy-book-store.herokuapp.com/books?_limit=10',
}, (error, reponse, body) => {
let data;
try {
data = JSON.parse(body); // 用 JSON.parse處理JSON格式的字串
} catch (error) {
console.log('error');
}
for (let i = 0; i < data.length; i++) {
//ES6 新語法 Template Literals:使用 ${ } 來加入變數或函式
//使用 ${ data[i].id } 來插入變數
console.log(`${data[i].id} ${data[i].name}`)
}
}
);
範例2 串接API,可以手動加入參數後顯示前 20 本書的資料、刪除、新增以及修改書本
參考資料 JavaScript switch 語法
參考資料 AJAX JavaScript 與 jQuery 教學範例 for PHP
學習看request文件
Base URL
: https://lidemy-book-store.herokuapp.com
小補充 : process
模組
process
是 Node.js
內建的模組,功能為「 取得指令的參數 」。
const process = require('process')
process.argv
印出process.argv 觀察使用方法
console.log(process.argv)
會發現印出來的是一個陣列,arr[0]是 node、 arr[1]是 server.js ,arr[2]可以得到 我們要的內容。
結論:使用process.argv
會從arr[2]開始使用 :process.argv[2]
// 顯示前 20 本書的資料、刪除、新增以及修改書本
// 串接API
// 引入了request的library
const request = require('request');
// 讀取使用者下的參數
const args = process.argv;
const apiUrl = 'https://lidemy-book-store.herokuapp.com';
const action = args[2];
const params = args[3];
// ES6 新語法 Template Literals:使用 ${ } 來加入變數或函式
// 使用 ${ apiUrl } 來插入變數
function listBooks() {
// eslint-disable-next-line consistent-return
request(`${apiUrl}/books?_limit=20`, (error, response, body) => {
if (error) {
// eslint-disable-next-line no-console
return console.log('讀取資料失敗', error);
}
const data = JSON.parse(body);
for (let i = 0; i < data.length; i += 1) {
// eslint-disable-next-line no-console
console.log(`${data[i].id} ${data[i].name}`);
}
});
}
function readBook(id) {
// eslint-disable-next-line consistent-return
request(`${apiUrl}/books/${id}`, (error, response, body) => {
if (error) {
// eslint-disable-next-line no-console
return console.log('讀取資料失敗', error);
}
const data = JSON.parse(body);
// eslint-disable-next-line no-console
console.log(data);
});
}
function deleteBook(id) {
// eslint-disable-next-line consistent-return
request.delete(`${apiUrl}/books/${id}`, (error) => {
if (error) {
// eslint-disable-next-line no-console
return console.log('刪除失敗', error);
}
// eslint-disable-next-line no-console
console.log('刪除成功!');
});
}
function createBook(name) {
request.post({
url: `${apiUrl}/books`,
form: {
name,
},
// eslint-disable-next-line consistent-return
}, (error) => {
if (error) {
// eslint-disable-next-line no-console
return console.log('新增失敗', error);
}
// eslint-disable-next-line no-console
console.log('新增成功!');
});
}
function updateBook(id, name) {
request.patch({
url: `${apiUrl}/books/${id}`,
form: {
name,
},
// eslint-disable-next-line consistent-return
}, (error) => {
if (error) {
// eslint-disable-next-line no-console
return console.log('更新失敗', error);
}
// eslint-disable-next-line no-console
console.log('更新成功!');
});
}
// switch 語法
// 變數的值是 list,則會執行 case 'list': listBooks();區塊的程式碼
switch (action) {
case 'list':
listBooks();
break;
case 'read':
readBook(params);
break;
case 'delete':
deleteBook(params);
break;
case 'create':
createBook(params);
break;
case 'update':
updateBook(params, args[4]);
break;
default:
// eslint-disable-next-line no-console
console.log('Available commands: list, read, delete, create and update');
}
範例3 串接API,輸入國家的英文名字,就能夠查詢符合的國家的資訊
參考資料 AJAX JavaScript 與 jQuery 教學範例 for PHP
參考資料 30 天 Javascript 從入門到進階:物件
參考資料 JavaScript Template String 樣板字串
學習看API文件
// 輸入國家的英文名字,就能夠查詢符合的國家的資訊
// 引入了request的library
const request = require('request');
// 讀取使用者下的參數
const args = process.argv;
const apiUrl = 'https://restcountries.eu/rest/v2';
const name = args[2];
// ES6 新語法 Template Literals:使用 ${ } 來加入變數或函式
// 使用 ${ apiUrl } 來插入變數
// eslint-disable-next-line
request(`${apiUrl}/name/${name}`, (error, response, body) => {
if (error) {
return console.log('讀取資料失敗', error);
}
// 用 JSON.parse處理JSON格式的字串
// eslint-disable-next-line
let data = JSON.parse(body);
// status 請求回應狀態,也就是 HTTP 狀態碼(status code)
// 4xx:客戶端錯誤 表示客戶端提交的請求中有錯誤或者不能被完成
if (data.status >= 400 && data.status < 500) {
return console.log('找不到國家資訊');
}
// node hw3.js korea
// args[2] 需要是國家名稱
if (!name) {
return console.log('請輸入國家名稱');
}
for (let i = 0; i < data.length; i += 1) {
console.log('========================');
// ES6 新語法 Template Literals:使用 ${ } 來加入變數或函式
// 使用 ${ data[i].id } 來插入變數
console.log(`國家: ${data[i].name}`);
console.log(`首都: ${data[i].capital}`);
console.log(`貨幣: ${data[i].currencies[0].code}`);
console.log(`國碼: ${data[i].callingCodes[0]}`);
}
});
範例4 串接API,呼叫 Twitch API,並拿到「最受歡迎的遊戲列表(Get Top Games)」
依序印出目前觀看人數跟遊戲名稱
參考資料 AJAX JavaScript 與 jQuery 教學範例 for PHP
參考資料 突發任務:Twitch API
參考資料 輕鬆理解 Ajax 與跨來源請求
參考資料 JavaScript ES6 中的 for … of(處理陣列的好幫手)
參考資料 30 天 Javascript 從入門到進階:物件
學習看request文件
學習看API文件
在 request header 中帶上 ClientID 跟另一個參數 Accept
從API文件觀察 如何取得baseUrl
從API文件觀察 如何取得目前觀看人數跟遊戲名稱的資料
// 呼叫 Twitch API,並拿到「最受歡迎的遊戲列表(Get Top Games)」
// 依序印出目前觀看人數跟遊戲名稱
// 引入了request的library
const request = require('request');
// Twitch developer dashboard 註冊一個新的 Application 會拿到一個 ClientID
const clientID = 'br15dzlr0ukquy97xhv00y3i9r9g4x';
const baseUrl = 'https://api.twitch.tv/kraken';
request({
method: 'GET',
//拿到「最受歡迎的遊戲列表(Get Top Games)」
url: `${baseUrl}/games/top`,
headers: {
'Client-ID': clientID,
'Accept': 'application/vnd.twitchtv.v5+json'
}
}, function(error,response,body){
if(error){
return console.log(error)
}
// 用 JSON.parse處理JSON格式的字串
const data = JSON.parse(body)
const games = data.top
//ES6 語法 for...of
//可以把陣列的值一個個取出
for(let game of games) {
//用 . 來取得物件的資料
console.log(game.viewers + ' ' + game.game.name)
}
})
Lidemy HTTP Challenge
第一關
用 GET
方法跟圖書館管理員lib
說我的名字
const request = require('request');
request.get(
{ // 把名字傳給lib
url: 'https://lidemy-http-challenge.herokuapp.com/lv1?token={GOGOGO}&name=ruofan',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第二關
幫lib
找一本書
const request = require('request');
request.get(
{
// 從api文件取得書籍得資料
url: 'https://lidemy-http-challenge.herokuapp.com/api/books/56?token={HellOWOrld}&id=56',
// 再傳給lib
url: 'https://lidemy-http-challenge.herokuapp.com/lv2?token={HellOWOrld}&id=56',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第三關
const request = require('request');
request.post(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/books?token={5566NO1}',
form: {
name: '大腦喜歡這樣學',
ISBN: '9789863594475',
},
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
request.get(
{ // 把名字傳給lib
url: 'https://lidemy-http-challenge.herokuapp.com/lv3?token={5566NO1}&id=1989',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第四關
參考資料 Postman - 測試 API 神器 1/2
參考資料 使用 JS 解析網址與處理網址中的參數(URL Parameters)
解法
encodeURI()
轉換網址Base URL
: https://lidemy-http-challenge.herokuapp.com/api
const request = require('request');
let str = '世界';
let uri = encodeURI(`https://lidemy-http-challenge.herokuapp.com/api/books?q=${str}`);
request.get(uri, function (error, response, body) {
console.log(JSON.parse(body));
});
postman
使用postman
找到書名含有『世界』的書,id:79
即是我們要的那一本!
[{"id":2,"name":"當我想你時,全世界都救不了我","author":"肆一","ISBN":"5549173495"},{"id":27,"name":"從你的全世界路過","author":"張嘉佳","ISBN":"8426216529"},{"id":79,"name":"世界末日與冷酷異境","author":"村上春樹","ISBN":"9571313408"},{"id":90,"name":"文學的40堂公開課:從神話到當代暢銷書,文學如何影響我們、帶領我們理解這個世界","author":"約翰.薩德蘭","ISBN":"7978376866"}]
const request = require('request');
request.get(
{
// 從api文件取得書籍得資料
url: 'https://lidemy-http-challenge.herokuapp.com/api/books/79?token={LEarnHOWtoLeArn}&id=79',
// 再傳給lib
url: 'https://lidemy-http-challenge.herokuapp.com/lv4?token={LEarnHOWtoLeArn}&id=79',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第五關
幫忙刪除id:23
的書
const request = require('request');
request.delete(
{
// 從api文件取得書籍得資料
url: 'https://lidemy-http-challenge.herokuapp.com/api/books/23?token={HarukiMurakami}&id=23',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第六關
參考資料 小白合送的土耳其絨毯- Http Basic Authentication
參考資料 Java String Base64 編碼(Encode)及解碼(Decode)
參考資料 HTTP認證(HTTP Authentication)
Node.js 可使用
Buffer.from() 進行 base64 編碼
關鍵字 http basic authorization
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
//console.log(base64Str);
request.get(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/me',
url: 'https://lidemy-http-challenge.herokuapp.com/lv6?token={CHICKENCUTLET}&email=lib@lidemy.com',
headers: {
'Authorization': `Basic ${base64Str}`
}
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
HTTP Basic
編碼前
Authorization: Basic base64(admin:admin123)
使用 BASE64編碼器 轉換
編碼後
Authorization: Basic YWRtaW46YWRtaW4xMjM=
postman
驗證方法為傳入 Authorization 的 Header
base API
:https://lidemy-http-challenge.herokuapp.com/api/v2/me
將 email 放在 queryString
const request = require('request');
request.get(
{
url: 'https://lidemy-http-challenge.herokuapp.com/lv6?token={CHICKENCUTLET}&email=lib@lidemy.com',
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
第七關
id:89
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
//console.log(base64Str);
request.delete(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/89',
headers: {
'Authorization': `Basic ${base64Str}`
}
},
(error, response, body) => {
// eslint-disable-next-line no-console
console.log(body);
},
);
postman
一樣是 DELETE 方法,不同的是,這次要加上剛剛的 Authorization
第八關
查詢書名含有『我』的書籍
encodeURI()
轉換網址
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
let queryStr = '我';
let uri = encodeURI(`https://lidemy-http-challenge.herokuapp.com/api/v2/books?q=${queryStr}`);
request.get(
{
uri,
headers: {
'Authorization': `Basic ${base64Str}`
}
}, (error, response, body) =>{
console.log(JSON.parse(body));
},
);
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
request.patch(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/72',
contentType: 'application/x-www-form-urlencoded',
headers: {
'Authorization': `Basic ${base64Str}`
},
form: {
name: '日日好日:茶道教我的幸福15味【電影書腰版】',
ISBN: '9981835423'
}
}, (error, response, body) =>{
console.log(JSON.parse(body));
},
);
postman
[{"id":2,"name":"當我想你時,全世界都救不了我","author":"肆一","ISBN":"5549173495"},{"id":3,"name":"我殺的人與殺我的人","author":"東山彰良","ISBN":"9262228645"},{"id":7,"name":"你已走遠,我還在練習道別","author":"渺渺","ISBN":"3722233689"},{"id":9,"name":"你是我最熟悉的陌生人","author":"Middle","ISBN":"9765734253"},{"id":22,"name":"我輩中人:寫給中年人的情書","author":"張曼娟","ISBN":"7241428897"},{"id":38,"name":"我和我追逐的垃圾車","author":"謝子凡","ISBN":"7797349452"},{"id":57,"name":"我的櫻花戀人","author":"宇山佳佑","ISBN":"2947749939"},{"id":60,"name":"你走慢了我的時間","author":"張西","ISBN":"8811544334"},{"id":66,"name":"我是許涼涼","author":"李維菁","ISBN":"8389193464"},{"id":72,"name":"日日好日:茶道教我的幸福15味【電影書腰版】","author":"森下典子","ISBN":"9981835427"},{"id":90,"name":"文學的40堂公開課:從神話到當代暢銷書,文學如何影響我們、帶領我們理解這個世界","author":"約翰.薩德蘭","ISBN":"7978376866"},{"id":95,"name":"我想吃掉你的胰臟【電影珍藏版】","author":"住野夜","ISBN":"2615985356"},{"id":100,"name":"慢情書:我們會在更好的地方相遇嗎?","author":"林達陽","ISBN":"7418527246"}]
作者的名字是四個字,key 錯的 ISBN 最後一碼為 7
id:79
這本書符合我們要找的資訊
{"id":72,"name":"日日好日:茶道教我的幸福15味【電影書腰版】","author":"森下典子","ISBN":"9981835427"}
PATCH方法修改書籍的 ISBN 資訊 (一樣須帶驗證)
第九關
想要存取的話要符合兩個條件:
X-Library-Number
的 header
,我們圖書館的編號是 20user agent
檢查是否是從 IE6
送出的 Request
,不是的話會擋掉偽造IE6的 request header
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
request.get(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/sys_info',
headers: {
'Authorization': `Basic ${base64Str}`,
'X-Library-Number': 20,
'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)',
}}, (error, response, body) =>{
console.log(JSON.parse(body));
},
);
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
request.get(
{
url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/sys_info',
url:'https://lidemy-http-challenge.herokuapp.com/lv9?token={NeuN}&version=1A4938Jl7',
headers: {
'Authorization': `Basic ${base64Str}`,
'X-Library-Number': 20,
'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)',
}}, (error, response, body) =>{
console.log(body);
},
);
postman
query string 回傳剛剛得到的 version資訊
第十關
出題者會出一個四位數不重複的數字,例如說 9487
。
如果猜 9876
,lib
會說 1A2B
,1A
代表 9
位置對數字也對,2B
代表 8
跟 7
你猜對了但位置錯了。
把要猜的數字放在 query string
用 num
當作 key
傳給 lib
const request = require('request');
let account = 'admin';
let pwd = 'admin123';
let base64Str = Buffer.from(`${account}:${pwd}`).toString('base64');
request.get(
{
url:'https://lidemy-http-challenge.herokuapp.com/lv10?token={duZDsG3tvoA}&num=9613',
headers: {
'Authorization': `Basic ${base64Str}`
}
}, (error, response, body) =>{
console.log(body);
},
);
postman
第十一關
跟菲律賓的圖書館館員打招呼
Base URL
: https://lidemy-http-challenge.herokuapp.com/api/v3
hint: 伺服器會檢查 origin 這個 header,只要騙過伺服器就行了
request header 內偽造 origin
參考資料 用 node.js 呼叫 API 與在網頁上呼叫的根本差異是什麼?
Request 從瀏覽器發出來:有許多限制
自己發 Request:沒有限制
參考資料 mozilla
const request = require('request');
request.get(
{
url:'https://lidemy-http-challenge.herokuapp.com/api/v3/hello',
headers: {
'origin': 'lidemy.com',
}
}, (error, response, body) =>{
console.log(body);
},
);
postman
第十二關
server side redirect 的原理
轉址背後的原理
參考資料 3分鐘了解 301 與 302 Redirect 重定向之間的差異與它們如何影響網站 SEO 排名
使用 chrome 開發者工具
,在 Network 分頁
中觀察 request
,網址列中輸入以下網址,訪問 API
https://lidemy-http-challenge.herokuapp.com/api/v3/deliver_token
被轉址到其他地方了
deliver_token > stopover > deliver_token_result
透過 Network 分頁觀察 stopover
,發現 header
內夾帶 X-Lv13-Token: {qspyz}
第十三關
hint 找關鍵字 代理伺服器 proxy
第十四關
參考資料 User-Agent 說明與使用
各個搜尋引擎的User-Agent
User-Agent
可以設定要使用哪種搜尋引擎
const request = require('request');
request.get(
{ // 獲取首頁內容
url:'https://lidemy-http-challenge.herokuapp.com/api/v3/index',
headers: {
'origin': 'lidemy.com',
'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
}
}, (error, response, body) =>{
console.log(body);
},
);
XML
& JSON
XML
以前傳資料的格式,現代開發比較少用
JSON
比起 XML 更輕量,為現代最普遍、常用的資料格式。
RESTful API
現代 API 有一大部分都是走 RESTful 設計風格。
參考資料 RESTful的一點心得小記
是一種廣泛流行的 API 設計規範、不是規定
參考資料 Linux Curl Command 指令與基本操作入門教學
curl -X GET "http://www.example.com/api/resources"
curl -X POST -H "Content-Type: application/json" -d '{"status" : false, "name" : "Jack"}' "http://www.example.com/api/resources"
curl -X DELETE "http://www.example.com/api/resources/1
參考資料 Linux Curl Command 指令與基本操作入門教學
參考資料 API 實作(三):以 Postman 測試 API
透過 HTTP Protocol下載和上傳檔案的指令
curl [options] [URL...]
用 curl 發 request 到 google 首頁
curl 後面加網址,就會在終端機內顯示回傳的 response,可能是 HTML、JSON 或是 XML 等格式,根據輸入的 URL 內容而定。
curl http://www.google.com
RESTful API
curl -X [method] [url]
curl -X GET "http://localhost:3000/article/1"