from flask import Flask, jsonify, request
app = Flask(__name__)
books = [
{'id': 1, 'title': '1984', 'author': 'George Orwell'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee'}
]
@app.route('/books', methods=['GET'])
def get_books():
return jsonify(books)
@app.route('/books', methods=['POST'])
def add_book():
new_book = request.get_json()
books.append(new_book)
return jsonify(new_book), 201
@app.route('/books/<int:id>', methods=['PUT'])
def update_book(id):
book = next((b for b in books if b['id'] == id), None)
if book is None:
return jsonify({'error': 'Book not found'}), 404
data = request.get_json()
book.update(data)
return jsonify(book)
@app.route('/books/<int:id>', methods=['DELETE'])
def delete_book(id):
global books
books = [b for b in books if b['id'] != id]
return '', 204
if __name__ == '__main__':
app.run(debug=True)

在本示例中,API 定義了多個用于管理圖書的端點(路由)。每個端點都允許客戶對圖書資源執行特定操作。

什么是端點?

端點是提供特定服務的特定 URL 模式。它代表通信通道的一端,通常與應用程序接口公開的操作相對應。

端點是應用程序接口的重要組成部分。它們定義了訪問或操作資源的位置和方式。

示例:網絡應用程序接口中的端點

繼續前面的例子,讓我們來確定端點:

GET /books:獲取所有書籍的列表。

POST /books:添加新書

PUT /books/<int:id>: 用指定的 ID 更新圖書。

DELETE /books/<int:id>: 刪除指定 ID 的圖書。

每個端點都執行不同的操作,允許客戶以特定方式與圖書資源交互。

應用程序接口與端點的主要區別

  1. 范圍:應用程序接口:應用程序接口(API)是一個更寬泛的概念,包括一套用于構建和集成軟件應用程序的規則和定義。它包括多個端點。端點:端點是 API 中執行特定功能的特定 URL 模式。
  2. 功能:應用程序接口:應用程序接口(API)定義了不同軟件組件的交互方式。它為訪問應用程序的功能和數據提供了一個完整的接口。端點:端點是應用程序接口中執行操作的特定交互點。
  3. 結構:應用程序接口:應用程序接口由多個端點組成,每個端點處理應用程序功能的特定部分。端點:端點是應用程序接口中與特定操作相對應的一個點。

詳細代碼示例

為了進一步說明應用程序接口和端點之間的區別和互動,讓我們擴展前面的示例。我們將添加更多的功能,并展示端點如何在更廣泛的 API 環境中工作。

添加身份驗證

讓我們為應用程序接口添加身份驗證。只有通過身份驗證的用戶才能添加、更新或刪除圖書。

from flask import Flask, jsonify, request, abort
app = Flask(__name__)
books = [
{'id': 1, 'title': '1984', 'author': 'George Orwell'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee'}
]
users = {
'user1': 'password1',
'user2': 'password2'
}
def authenticate():
auth = request.authorization
if not auth or not users.get(auth.username) == auth.password:
return False
return True
@app.route('/books', methods=['GET'])
def get_books():
return jsonify(books)
@app.route('/books', methods=['POST'])
def add_book():
if not authenticate():
return jsonify({'error': 'Unauthorized access'}), 401
new_book = request.get_json()
books.append(new_book)
return jsonify(new_book), 201
@app.route('/books/<int:id>', methods=['PUT'])
def update_book(id):
if not authenticate():
return jsonify({'error': 'Unauthorized access'}), 401
book = next((b for b in books if b['id'] == id), None)
if book is None:
return jsonify({'error': 'Book not found'}), 404
data = request.get_json()
book.update(data)
return jsonify(book)
@app.route('/books/<int:id>', methods=['DELETE'])
def delete_book(id):
if not authenticate():
return jsonify({'error': 'Unauthorized access'}), 401
global books
books = [b for b in books if b['id'] != id]
return '', 204
if __name__ == '__main__':
app.run(debug=True)

在本例中,驗證函數會檢查請求是否包含有效的驗證憑證。POST、PUT 和 DELETE 端點受保護,需要有效憑證才能訪問。

添加錯誤處理

讓我們通過添加更詳細的錯誤處理來改進我們的應用程序接口。這樣可以確保客戶在出錯時收到有意義的錯誤信息。

from flask import Flask, jsonify, request, abort
app = Flask(__name__)
books = [
{'id': 1, 'title': '1984', 'author': 'George Orwell'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee'}
]
users = {
'user1': 'password1',
'user2': 'password2'
}
def authenticate():
auth = request.authorization
if not auth or not users.get(auth.username) == auth.password:
return False
return True
@app.errorhandler(400)
def bad_request(error):
return jsonify({'error': 'Bad request'}), 400
@app.errorhandler(401)
def unauthorized(error):
return jsonify({'error': 'Unauthorized access'}), 401
@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Resource not found'}), 404
@app.route('/books', methods=['GET'])
def get_books():
return jsonify(books)
@app.route('/books', methods=['POST'])
def add_book():
if not authenticate():
abort(401)
if not request.json or not 'title' in request.json:
abort(400)
new_book = {
'id': books[-1]['id'] + 1 if books else 1,
'title': request.json['title'],
'author': request.json.get('author', "")
}
books.append(new_book)
return jsonify(new_book), 201
@app.route('/books/<int:id>', methods=['PUT'])
def update_book(id):
if not authenticate():
abort(401)
book = next((b for b in books if b['id'] == id), None)
if book is None:
abort(404)
if not request.json:
abort(400)
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
return jsonify(book)
@app.route('/books/<int:id>', methods=['DELETE'])
def delete_book(id):
if not authenticate():
abort(401)
global books
books = [b for b in books if b['id'] != id]
return '', 204
if __name__ == '__main__':
app.run(debug=True)

在這個改進版本中,我們為不同的 HTTP 狀態代碼添加了自定義錯誤處理程序。中止函數用于在必要時觸發這些錯誤處理程序,為客戶端提供更多的錯誤信息。

高級概念:版本控制和速率限制

隨著應用程序接口的復雜性不斷增加,管理不同版本和限制請求率以確保穩定性和向后兼容性變得至關重要。

應用程序接口版本化

應用程序接口版本管理允許您維護不同版本的應用程序接口,以支持傳統客戶端,同時為新客戶端添加新功能。讓我們為應用程序接口添加版本控制。

from flask import Flask, jsonify, request, abort
app = Flask(__name__)
books_v1 = [
{'id': 1, 'title': '1984', 'author': 'George Orwell'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee'}
]
books_v2 = [
{'id': 1, 'title': '1984', 'author': 'George Orwell', 'published': '1949'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee', 'published': '1960'}
]
users = {
'user1': 'password1',
'user2': 'password2'
}
def authenticate():
auth = request.authorization
if not auth or not users.get(auth.username) == auth.password:
return False
return True
@app.route('/v1/books', methods=['GET'])
def get_books_v1():
return jsonify(books_v1)
@app.route('/v1/books', methods=['POST'])
def add_book_v1():
if not authenticate():
abort(401)
if not request.json or not 'title' in request.json:
abort(400)
new_book = {
'id': books_v1[-1]['id'] + 1 if books_v1 else 1,
'title': request.json['title'],
'author': request.json.get('author', "")
}
books_v1.append(new_book)
return jsonify(new_book), 201
@app.route('/v1/books/<int:id>', methods=['PUT'])
def update_book_v1(id):
if not authenticate():
abort(401)
book = next((b for b in books_v1 if b['id'] == id), None)
if book is None:
abort(404)
if not request.json:
abort(400)
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
return jsonify(book)
@app.route('/v1/books/<int:id>', methods=['DELETE'])
def delete_book_v1(id):
if not authenticate():
abort(401)
global books_v1
books_v1 = [b for b in books_v1 if b['id'] != id]
return '', 204
@app.route('/v2/books', methods=['GET'])
def get_books_v2():
return jsonify(books_v2)
@app.route('/v2/books', methods=['POST'])
def add_book_v2():
if not authenticate():
abort(401)
if not request.json or not 'title' in request.json:
abort(400)
new_book = {
'id': books_v2[-1]['id'] + 1 if books_v2 else 1,
'title': request.json['title'],
'author': request.json.get('author', ""),
'published': request.json.get('published', "")
}
books_v2.append(new_book)
return jsonify(new_book), 201
@app.route('/v2/books/<int:id>', methods=['PUT'])
def update_book_v2(id):
if not authenticate():
abort(401)
book = next((b for b in books_v2 if b['id'] == id), None)
if book is None:
abort(404)
if not request.json:
abort(400)
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
book['published'] = request.json.get('published', book['published'])
return jsonify(book)
@app.route('/v2/books/<int:id>', methods=['DELETE'])
def delete_book_v2(id):
if not authenticate():
abort(401)
global books_v2
books_v2 = [b for b in books_v2 if b['id'] != id]
return '', 204
if __name__ == '__main__':
app.run(debug=True)

在本例中,我們創建了兩個版本的應用程序接口(v1 和 v2)。每個版本都有自己的端點集,允許客戶選擇與哪個版本進行交互。 這種方法有助于保持向后兼容性,同時又能引入新的功能和改進。

速率限制

速率限制為客戶在一定時間內向應用程序接口發出的請求數量設置了上限。這樣可以確保客戶端之間的公平使用,防止濫用。讓我們使用 flask-limiter 擴展為我們的應用程序接口提供速率限制。

from flask import Flask, jsonify, request, abort
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
get_remote_address,
app=app,
default_limits=["200 per day", "50 per hour"]
)
books = [
{'id': 1, 'title': '1984', 'author': 'George Orwell'},
{'id': 2, 'title': 'To Kill a Mockingbird', 'author': 'Harper Lee'}
]
users = {
'user1': 'password1',
'user2': 'password2'
}
def authenticate():
auth = request.authorization
if not auth or not users.get(auth.username) == auth.password:
return False
return True
@app.errorhandler(400)
def bad_request(error):
return jsonify({'error': 'Bad request'}), 400
@app.errorhandler(401)
def unauthorized(error):
return jsonify({'error': 'Unauthorized access'}), 401
@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Resource not found'}), 404
@app.errorhandler(429)
def ratelimit_error(error):
return jsonify({'error': 'Too many requests'}), 429
@app.route('/books', methods=['GET'])
@limiter.limit("10 per minute")
def get_books():
return jsonify(books)
@app.route('/books', methods=['POST'])
@limiter.limit("5 per minute")
def add_book():
if not authenticate():
abort(401)
if not request.json or not 'title' in request.json:
abort(400)
new_book = {
'id': books[-1]['id'] + 1 if books else 1,
'title': request.json['title'],
'author': request.json.get('author', "")
}
books.append(new_book)
return jsonify(new_book), 201
@app.route('/books/<int:id>', methods=['PUT'])
@limiter.limit("5 per minute")
def update_book(id):
if not authenticate():
abort(401)
book = next((b for b in books if b['id'] == id), None)
if book is None:
abort(404)
if not request.json:
abort(400)
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
return jsonify(book)
@app.route('/books/<int:id>', methods=['DELETE'])
@limiter.limit("5 per minute")
def delete_book(id):
if not authenticate():
abort(401)
global books
books = [b for b in books if b['id'] != id]
return '', 204
if __name__ == '__main__':
app.run(debug=True)

在本例中,flask-limiter 擴展用于對不同端點應用速率限制。default_limits 參數設置了全局速率限制,而 @limiter.limit 裝飾器則為單個端點應用了特定的速率限制。 如果客戶端超過了允許的請求數,就會收到 429 請求過多的錯誤信息。

設計應用程序接口和端點的最佳實踐

  1. 一致性:確保 API 端點遵循一致的命名規范和結構。這將使客戶更容易理解和使用您的應用程序接口。
  2. 版本控制:使用版本管理來管理 API 的更改和改進,而不會破壞現有客戶端。為清晰起見,請首選基于 URL 的版本(如 /v1/resource)。
  3. 文檔:為您的應用程序接口提供全面的最新文檔。包括有關可用端點、請求/響應格式、驗證方法和錯誤處理的信息。
  4. 錯誤處理:實施有意義的錯誤信息和適當的 HTTP 狀態代碼。這有助于客戶了解出錯的原因以及如何修復。
  5. 安全性:使用驗證和授權機制保護您的應用程序接口。確保使用 HTTPS 安全傳輸敏感數據。
  6. 速率限制:實施速率限制,防止濫用并確保公平使用。根據 API 和客戶的需求自定義速率限制。
  7. 測試:徹底測試您的應用程序接口,確保其按預期運行。使用自動化測試工具來覆蓋各種場景和邊緣情況。
  8. 監控:監控您的應用程序接口,以便及時發現并解決問題。使用日志和監控工具跟蹤性能、錯誤和使用模式。

結論

應用程序接口(API)和端點是網絡開發中的基本概念,各自在實現軟件應用程序之間的通信方面發揮著不同的作用。了解應用程序接口和端點之間的區別對于設計穩健高效的系統至關重要。

在這篇博文中,我們探討了 API 和端點的概念,強調了它們的區別,并提供了詳細的代碼示例來說明它們的用法。我們還討論了版本控制和速率限制等高級主題,以及設計 API 的最佳實踐。

通過遵循這些指導原則和最佳實踐,您可以創建不僅功能齊全,而且安全、可擴展和易于使用的應用程序接口。 無論您是在構建簡單的應用程序還是復雜的系統,對應用程序接口和端點的扎實了解都將有助于您提供高質量的軟件解決方案。

原文鏈接:https://medium.com/@nile.bits/apis-vs-endpoints-breaking-down-the-differences-ef80ef128844

推薦閱讀:
REST API:關鍵概念、最佳實踐和優勢
7個API業務模型術語
了解異步API
API 安全策略和基礎指南
在線API描述規范、發現與文檔入門
API設計模式:粒度細化 vs 粒度粗化的利弊分析

上一篇:

首次構建 API 時的 10 個錯誤狀態代碼以及如何修復它們

下一篇:

常見問題解答:什么是 API Key 密鑰?
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費