建议关注收藏,持续更新技术文档。
目录
API v.s. REST API
REST APIs : representational state transfer APIs
特性:through the Internet
- 任何一个软件的方法调用都可以称为API;REST API指的是基于网络的某种Web API
- data format
API可用(JSON, XML, and so on),而REST API用的是轻量的数据格式JSON
HTTP message
REST APIs over HTTP
-
Request methods (HTTP methods):GET/POST/PUT/DELETE
-
Request headers
Headers contain additional information about the request, such as the content type, authentication tokens, or other metadata. -
Request body
Sometimes, a request may include a body containing data that someone wants sent to the server. This request body is common in POST or PUT requests, where the client sends data to create or update a resource. -
Response status code
-
Authentication身份验证
Many APIs require authentication to ensure that only authorized users or applications can access certain resources—some examples of using API keys include OAuth tokens or other authentication mechanisms. -
Documentation
Good API design includes comprehensive documentation that explains how to use the API, the available endpoints, request and response formats, and any authentication requirements. This documentation helps you as a developer to understand and integrate with the API effectively.
Structure of API URL
-
Uniform resource identifier (URI)
-
Uniform resource locator (URL)
注意区分URL v.s. URI
URL: https://api.example.com
URI:https://api.example.com/v1/get/json.xmlparameter1=value1¶meter2=value2 I -
Route:This is the location on the web server; for example: /v1/get/json.xml
初步尝试
Apache、IIS、Nginx等绝大多数web服务器,都不允许静态文件响应POST请求,否则会返回“HTTP/1.1 405 Method not allowed”错误。
# Import the requests and json modules for making HTTP requests and handling JSON data, respectively.
import requests
import json
# Specify the URL of the API endpoint for retrieving information about fish species.
url = "https://www.fishwatch.gov/api/species"
# Make an HTTP GET request to the specified URL and store the response in the data variable.
data = requests.get(url)
# Parse the JSON data received from the API response using json.loads() and store it in the results variable.
results = json.loads(data.text)
url_get='http://abc.org/get'
payload={"name":"a","ID":"123"}
r=requests.get(url_get,params=payload)
r.url #'http://abc.org/get?name=a&ID=123'
r.request.body #None
r.status_code#200
r.text
r.headers['Content-Type']
r.json() #return python dict
#注意get,post 在url/body/json等上面的区别
url_post='http://abc.org/post'
payload={"name":"a","ID":"123"}
r_post=requests.post(url_post,params=payload)
r_post.url #'http://abc.org/post'
r_post.request.body #name=a&ID=123'
r.status_code#200
r.text
r.headers['Content-Type']
r.json() #return python dict
python_api:flask+flask_restful
在开始之前呢,我们需要安装几个模块,flask+flask_restful
- 注意:如果还没部署到服务器上,只是在本地使用,需要添加代码,否则会报错,尤其post方法用不了
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有来源,或者替换为具体的前端地址,如 ["http://localhost:3000"]
allow_credentials=True,
allow_methods=["*"], # 允许所有 HTTP 方法
allow_headers=["*"], # 允许所有请求头
)
# 日志中间件
# @app.middleware("http")
# async def log_requests(request: Request, call_next):
# print(f"收到请求: {request.method} {request.url}")
# response = await call_next(request)
# return response
- get接口
# coding=utf-8
import sys
import importlib
importlib.reload(sys)
from flask import *
import flask_restful
app = Flask(__name__)
api = flask_restful.Api(app)
class HelloWorld(flask_restful.Resource):
def get(self):
x=request.args['x']#获取参数中的值
y=request.args['y']
return {'hello':y,'donghu':x}#接口返回值
api.add_resource(HelloWorld, '/login',methods=['GET'])#页面路径
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80)#请求地址,以及端口
get接口编写完成,运行,然后在浏览器中输入http://127.0.0.1/login
能正常返回值,那就说明没有问题了。
- post接口
# coding=utf-8
import sys
import importlib
importlib.reload(sys)
from flask import *
import flask_restful
app = Flask(__name__)
api = flask_restful.Api(app)
class HelloWorld(flask_restful.Resource):
def post(self):
x = request.form['x']#获取参数
y=request.form['y']
return {'hello':y,'donghu':x}
api.add_resource(HelloWorld, '/login2',methods=['POST'])
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80)
post接口和get接口编写方式上差不多,只是接收参数的方式稍有调整。运行,然后在浏览器中输入,http://127.0.0.1/login2,看是否能正常访问。
python_api:FastAPI+Tornado
python提供了很多web框架,帮助我们快速构建API,如Flask、FastAPI、Tornado。
Flask、FastAPI如出一辙,所以这里只讲FastAPI+Tornado,如何构建GET和POST接口。
pip install fastapi
pip install uvicorn
pip install tornado
- FastAPI自动生成api文档
启动程序后,在浏览器中输入http://127.0.0.1:8000/docs - uvicorn (文件名不带.py):app --reload
–reload就是加入debug调试,什么叫debug调试?就是我们要修改里面的代码的时候,不需要重新运行,一边运行一边更改,。不加debug呢就是我文章有错别字,我需要把文章前面重新再写一遍,然后再改,大致是这个意思。
# -*- coding: utf-8 -*-
from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
'''
Pydantic 用于数据验证和解析的第三方库。
它提供了一种简单且直观的方式来定义数据模型,
并使用这些模型对数据进行验证和转换。
Uvicorn 是一个快速的 ASGI(Asynchronous Server Gateway Interface)服务器
用于构建异步 Web 服务。
它基于 asyncio 库,支持高性能的异步请求处理,适用于各种类型的 Web 应用程序。
'''
app = FastAPI()
class Item(BaseModel):
a: int = None
b: int = None
@app.get('/test/a={a}/b={b}')
def calculate(a: int=None, b: int=None):
c = a + b
res = {"res":c}
return res
@app.post('/test')
def calculate(request_data: Item):
a = request_data.a
b = request_data.b
c = a + b
res = {"res":c}
return res
if __name__ == '__main__':
uvicorn.run(app=app,
host="localhost",
port=8000,
workers=1)
将上述代码保存为get.py,存储在某一路径
首先,进入python文件路径,在控制台启动服务
浏览器测试:访问http://localhost:8000/test/a=31/b=12
postman测试:
FastAPI的交互测试:访问http://localhost:8000/docs
Tornado比FastAPI更能承受高并发。
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado import gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
import time
from tornado.options import define, options
from tornado.platform.asyncio import to_asyncio_future,AsyncIOMainLoop
from tornado.httpclient import AsyncHTTPClient
import asyncio
define("port", default=8000, help="just run", type=int)
class MainHandler(tornado.web.RequestHandler):
def main(self,a,b):
c = float(a) + float(b)
res = {"res":c}
return res
# get接口
def get(self):
a = self.get_body_argument('a')
b = self.get_body_argument('b')
res = self.main(a,b) # 主程序计算
self.write(json.dumps(res,ensure_ascii=False))
# post接口
def post(self):
a = self.get_body_argument('a')
b = self.get_body_argument('b')
res = int(a) * int(b) #主程序计算
self.write(json.dumps(res,ensure_ascii=False))
if __name__ == "__main__":
#运行程序
application = tornado.web.Application([(r"/test", MainHandler),])
application.listen(8000,'localhost')
tornado.ioloop.IOLoop.instance().start()