REST API 簡(jiǎn)介

注意,這里只是對(duì)REST API 的簡(jiǎn)單介紹,起到拋磚引玉作用,更加深入內(nèi)容不在本次學(xué)習(xí)范圍內(nèi),感興趣的小伙伴可以查看相關(guān)資料深入學(xué)習(xí)。此外本號(hào)接受該領(lǐng)域的投稿,歡迎聯(lián)系云朵君!

API

API,全名Application Programming Interface (應(yīng)用程式介面),簡(jiǎn)單來(lái)說(shuō),是品牌開(kāi)發(fā)出的一種接口,讓第三方可以額外開(kāi)發(fā)、應(yīng)用在自身的產(chǎn)品上的系統(tǒng)溝通介面。

REST API

REST 是一種通過(guò) HTTP 協(xié)議設(shè)計(jì) API 的架構(gòu)風(fēng)格。它的主要優(yōu)點(diǎn)是其極大的靈活性。只要需要直接從服務(wù)器向 Web 應(yīng)用程序或站點(diǎn)的用戶提供數(shù)據(jù),開(kāi)發(fā)人員就會(huì)使用 REST API

REST API 的主要組件:

REST API 通過(guò) HTTP 請(qǐng)求進(jìn)行通信,完成以下功能——?jiǎng)?chuàng)建、讀取、更新和刪除數(shù)據(jù)。它們也稱為 CRUD 操作。REST 提供有關(guān)請(qǐng)求資源的信息,并使用四種方法來(lái)描述如何處理資源:

RESTful API

REST,全名Representational State Transfer( 表現(xiàn)層狀態(tài)轉(zhuǎn)移),他是一種設(shè)計(jì)風(fēng)格,RESTful 只是轉(zhuǎn)為形容詞,像是 peace 和平這名詞,轉(zhuǎn)成形容詞是peaceful,RESTful 則形容以此規(guī)范設(shè)計(jì)的API,稱為RESTful API。

RESTful API 主要由三種元件組成:

所以使用 RESTful 風(fēng)格設(shè)計(jì)的API,就有了以下幾種優(yōu)點(diǎn)及限制:

  1. 有唯一的URL表示資源位置,統(tǒng)一的API 接口。(Uniform Interface)
  2. 無(wú)狀態(tài)。(Stateless)

Restful API 它允許集成應(yīng)用程序 app ?或與 Restful Web 服務(wù)交互。它現(xiàn)在正在成長(zhǎng)為連接微服務(wù)架構(gòu)中組件的最常用方法。我們借助 API,能夠獲取或發(fā)送數(shù)據(jù)到網(wǎng)站并執(zhí)行一些操作,目的是通過(guò) Web 服務(wù)完成我們的任務(wù)。每個(gè)網(wǎng)站都使用不同類型的 API,例如股票市場(chǎng)交易網(wǎng)站,借助 API 獲取當(dāng)前價(jià)格和上下波動(dòng)。

創(chuàng)建第一個(gè) REST API

同樣,我們創(chuàng)建 Hello world API,它表示如果你對(duì)其發(fā)出 get 請(qǐng)求,?將獲得 JSON 響應(yīng),一般情況下, API 給出 JSON 類型的響應(yīng)。接下來(lái),使用 pip 包管理器安裝 Flask:

pip install flask
pip install flask-restful

from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)

class Helloworld(Resource):
def __init__(self):
pass
def get(self):
return {
"Hello": "World"
}
api.add_resource(Helloworld, '/')

if __name__ == '__main__':
app.run(debug=True)

ok,到現(xiàn)在已經(jīng)創(chuàng)建了第一個(gè)Rest api,看起來(lái)挺簡(jiǎn)單的,那么,什么是Flask-Restful呢?

Flask restful 定義了資源Resource類,其中包含每個(gè) HTTP 方法的方法。方法名稱應(yīng)與其對(duì)應(yīng)的 HTTP 方法相同,并以小寫(xiě)形式書(shū)寫(xiě),如上代碼中所示。我們發(fā)現(xiàn)這些方法沒(méi)有路由裝飾器,這是它們是基于資源路由的。無(wú)論定義什么類,我們都可以使用添加資源add_resource方法定義到它的路由以及在對(duì)應(yīng)路由上調(diào)用該類?。

說(shuō)明: 在上面的代碼中,我們首先加載需要的父類,然后初始化我們的app和API。之后,我們創(chuàng)建了一個(gè)程序,并且我們正在發(fā)出一個(gè) GET 請(qǐng)求,說(shuō)明如果有人點(diǎn)擊了這個(gè)程序,那么他將得到 Hello world 作為 JSON 格式的響應(yīng)。要打開(kāi)特定 URL,我們使用 add resource 方法并將其路由到默認(rèn)斜杠。要運(yùn)行此文件,可以使用 POSTMAN 工具(一種 API 維護(hù)工具)來(lái)創(chuàng)建、測(cè)試和管理 API。還可以使用requests請(qǐng)求模塊使用以下代碼測(cè)試此 API。首先,運(yùn)行上面的文件,它會(huì)給你 localhost URL,然后在另一個(gè)命令提示符下,運(yùn)行下面的代碼文件:

import requests
url = "http://127.0.0.1:5000/"
response = requests.get(url=url)
print(response.text)
{
"Hello": "World"
}

通過(guò) Flask RESTApi 理解 HTTP 請(qǐng)求

通過(guò)以上內(nèi)容的學(xué)習(xí),相比大家已經(jīng)對(duì) REST API 有個(gè)初步印象。接下來(lái)我們將繼續(xù)探索使用 REST API 的不同 HTTP 方法,其中我們定義一個(gè)列表,該列表將以字典(JSON 對(duì)象)的形式存儲(chǔ)從服務(wù)器獲取的所有數(shù)據(jù)。這是很重要的,因?yàn)槲覀冊(cè)陧?xiàng)目中有不同的api來(lái)獲取數(shù)據(jù),而不是其他地方的數(shù)據(jù)。

首先創(chuàng)建一個(gè) API,在其中創(chuàng)建 3 個(gè)名為 GET、POST 和 DELETE 的 HTTP 方法,并且在其中創(chuàng)建一個(gè)自定義 URL,當(dāng)請(qǐng)求 POST 方法時(shí),它將以 Name 作為輸入;在請(qǐng)求 GET 方法時(shí),將名稱返回;在DELETE時(shí),如果該名稱存在,我們將刪除該名稱,再次訪問(wèn)它會(huì)給我們 NULL。

創(chuàng)建一個(gè)文件并編寫(xiě)以下代碼:

from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
data = []
class People(Resource):
def get(self):
for x in data:
if x['Data'] == name:
return x
return {'Data': None}
def post(self, name):
temp = {'Data': name}
data.append(temp)
return temp
def delete(self):
for ind, x in enumerate(data):
if x['Data'] == name:
temp = data.pop(ind)
return {'Note': 'Deleted'}
api.add_resource(People, '/Name/')
if __name__ == '__main__':
app.run(debug=True)

打開(kāi) POSTMAN API 工具并點(diǎn)擊每個(gè) HTTP 方法請(qǐng)求。首先,當(dāng)我們使用 post 請(qǐng)求Name時(shí),它給了我們一個(gè)name。在獲取請(qǐng)求時(shí),我們將返回name。它在刪除時(shí)被刪除,當(dāng)再次將其取回時(shí),它會(huì)給你返回 NULL。

結(jié)果如下

如何在 Flask REST API 中使用裝飾器

我們使用帶有 API 的裝飾器來(lái)監(jiān)控 IP 地址、cookie 等。我們將繼續(xù)學(xué)習(xí)如何使用帶有裝飾器的Flask API。裝飾器是一個(gè)將另一個(gè)函數(shù)作為參數(shù)并返回另一個(gè)函數(shù)的函數(shù)。也可以將其理解為在不改變或修改當(dāng)前功能的情況下,為現(xiàn)有功能提供一些附加功能的功能。

這里我們創(chuàng)建一個(gè)新文件,我將通過(guò)創(chuàng)建兩個(gè)裝飾器來(lái)展示。在第一個(gè)文件中,編寫(xiě)返回代碼執(zhí)行時(shí)間的外部時(shí)間函數(shù)。我們從 functools 模塊(用于高階 python 函數(shù)的標(biāo)準(zhǔn)模塊)導(dǎo)入應(yīng)用于 wrapper 函數(shù)的 wrap 裝飾器 。它通過(guò)復(fù)制所有參數(shù)來(lái)更新包裝函數(shù)。

from flask import Flask
from flask_restful import Resource, Api
import datetime
from flask import request
from functools import wraps
app = Flask(__name__)
api = Api(app)

def time(function=None):
@wraps(function)
def wrapper(*args, **kwargs):
s = datetime.datetime.now()
_ = function(*args, **kwargs)
e = datetime.datetime.now()
print("Execution Time : {} ".format(e-s))
return _
return wrapper
class HelloWorld(Resource):
@monitor
def get(self):
return {"hello": "world"}

api.add_resource(HelloWorld, "/")
if __name__ == "__main__":
app.run(debug=True)

我們創(chuàng)建第二個(gè)裝飾器來(lái)監(jiān)視cookie和IP地址,因此創(chuàng)建下面的函數(shù)。不是向hello world函數(shù)添加時(shí)間裝飾器,而是添加監(jiān)視器裝飾器并運(yùn)行代碼。

def monitor(function=None):
@wraps(function)
def wrapper(*args, **kwargs):
_ = function(*args, **kwargs)
print("Ip Address : {} ".format(request.remote_user))
print("Cookies : {} ".format(request.cookies))
print(request.user_agent)
return _
return wrapper

如何使 Flask API 更安全

當(dāng)我們?cè)O(shè)計(jì)API時(shí),我們也應(yīng)該注意安全性,因?yàn)楹芏嗳藭?huì)訪問(wèn)它。因?yàn)锳PI可能包含一些雙方之間的機(jī)密數(shù)據(jù),因此我們可以指定只有授權(quán)的人可以訪問(wèn)API,那該怎么辦?此時(shí)可以使用Flask基本身份驗(yàn)證。當(dāng)然,此時(shí)需要使用pip命令安裝這個(gè)flask模塊。

pip install flask-httpauth

我們正在構(gòu)建一個(gè)API并定義User數(shù)據(jù)字典,其中包含用戶名和密碼。當(dāng)在實(shí)時(shí)用例中工作時(shí),可以通過(guò)配置文件或從數(shù)據(jù)庫(kù)中接受用戶名和密碼。首先,我們創(chuàng)建一個(gè)主要函數(shù)來(lái)匹配用戶名和密碼,并創(chuàng)建一個(gè)GET方法,該方法表示任何點(diǎn)擊此API的人,如果沒(méi)有登錄,我們就無(wú)法訪問(wèn)數(shù)據(jù)。

from flask import Flask
from flask_restful import Resource, Api
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
api = Api(app, prefix="/api/v1")
auth = HTTPBasicAuth()
USER_DATA = {
"admin": "SuperSecretPwd"
}
#route to verify the password
@auth.verify_password
def verify(username, password):
if not(username and password):
return False
return USER_DATA.get(username) == password
class PrivateResource(Resource):
@auth.login_required
def get(self):
return {"How's the Josh": "High"}
api.add_resource(PrivateResource, '/private')
if __name__ == '__main__':
app.run(debug=True)

當(dāng)我們使用POSTMAN運(yùn)行上述文件時(shí),我們會(huì)嘗試在沒(méi)有登錄的情況下獲取數(shù)據(jù),以便給你演示未經(jīng)授權(quán)的訪問(wèn)權(quán)限。

現(xiàn)在轉(zhuǎn)到授權(quán),并單擊Basic authorization。輸入用戶名和密碼,然后點(diǎn)擊GET請(qǐng)求以獲得所需的結(jié)果。

這是保護(hù) Flask API 的方法,也是最基本的方法,當(dāng)然還有更多更高級(jí)的方法,這里不做過(guò)多的介紹。

如何在 Flask API 上啟用跟蹤

至此我們已經(jīng)了解了如何保護(hù)我們的 API,在未經(jīng)授權(quán)的登錄禁止訪問(wèn),但是如果我們還想知道訪問(wèn)者的位置(緯度和經(jīng)度點(diǎn))、IP 地址、服務(wù)器名稱(例如訪問(wèn)API 的人的詳細(xì)信息),我們還可以繼續(xù)配置,使用 REST API 的基本flask跟蹤應(yīng)用程序。首先,使用 PIP 命令安裝flask跟蹤包。

pip install flask-track-usage

接下來(lái)看下該程序:

from flask import Flask, g
app = Flask(__name__)
app.config['TRACK_USAGE_USE_FREEGEOIP'] = False
app.config['TRACK_USAGE_INCLUDE_OR_EXCLUDE_VIEWS'] = 'include'
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
t = TrackUsage(app, [
PrintWriter(),
OutputWriter(transform=lambda s: "OUTPUT: " + str(s))
])
@t.include
@app.route('/')
def index():
g.track_var["optional"] = "Write_Something"
return "Hello"
#Run the application
if __name__ == "__main__":
app.run(debug=True)

該程序通過(guò)導(dǎo)入 Track Usage、Input writer 和 output writer 來(lái)創(chuàng)建一個(gè)跟蹤應(yīng)用程序。將flask app傳遞給 Track 包并使用輸出編寫(xiě)器,并使用 lambda 函數(shù)以字符串格式寫(xiě)入輸出。之后在 slash 上創(chuàng)建一個(gè)基本路由,并將跟蹤應(yīng)用程序作為裝飾器包含在內(nèi)。g 代表全局,表示數(shù)據(jù)在上下文中是全局的。因此,創(chuàng)建一個(gè)基本 API,它在瀏覽器返回"Hello",同時(shí)在后端獲得所有人員的信息。

如何為REST API編寫(xiě)單元測(cè)試代碼

現(xiàn)在已經(jīng)為案例創(chuàng)建了一個(gè)不錯(cuò)的REST API。盡管如此,我們還需要為REST API編寫(xiě)單元測(cè)試代碼,因?yàn)閺腁PI中識(shí)別常見(jiàn)錯(cuò)誤,并確保生產(chǎn)安全是至關(guān)重要的。

如下是創(chuàng)建一個(gè)名為run的新文件并開(kāi)發(fā)以下簡(jiǎn)單API。

from flask import Flask
from flask_restful import Resource, Api
import json
app = Flask(__name__)
api = Api(app)
class Helloworld(Resource):
def __init__(self):
pass
def get(self):
return json.dumps({"Message": "Fine"})
api.add_resource(Helloworld, '/')
if __name__ == '__main__':
app.run(debug=True)

現(xiàn)在創(chuàng)建另一個(gè)名為test的文件,在其中編寫(xiě)用于對(duì)API進(jìn)行單元測(cè)試的代碼。最常見(jiàn)的情況是執(zhí)行以下三個(gè)基本單元測(cè)試。

from run import app
import unittest
class FlaskTest(unittest.TestCase):
#Check for response 200
def test_inde(self):
tester = app.test_client(self) #tester object
response = tester.get("/")
statuscode = response.status_code
self.assertEqual(statuscode, 200)
#check if the content return is application JSON
def test_index_content(self):
tester = app.test_client(self)
response = tester.get("/")
self.assertEqual(response.content_type, "application/json")
#check the Data returned
def test_index_data(self):
tester = app.test_client(self)
response = tester.get("/")
self.assertTrue(b'Message' in response.data)
if __name__ == '__main__':
unittest.main()

如果你已經(jīng)學(xué)習(xí)過(guò)網(wǎng)絡(luò)爬蟲(chóng),你應(yīng)該知道 200 響應(yīng)意味著對(duì)特定 URL 的請(qǐng)求已成功發(fā)出,并返回響應(yīng)。

好了,這就是本文的全部?jī)?nèi)容。到這里我們已經(jīng)學(xué)會(huì)了從頭開(kāi)始創(chuàng)建 Flask REST API ,并輕松安全地對(duì)其進(jìn)行維護(hù)。

文章轉(zhuǎn)自微信公眾號(hào)@數(shù)據(jù)STUDIO

上一篇:

用FastAPI實(shí)現(xiàn)簡(jiǎn)單的微服務(wù)API網(wǎng)關(guān)

下一篇:

從 Flask 切到 FastAPI 后,起飛了
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門(mén)場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)