之前已经 在腾讯云 SCF 上部署了 OneDrive 网盘,它的计费指标是调用次数、资源使用量和外网出流量。前两者有很大的免费额度,个人根本使用不完。而外网出流量的价格是 0.8¥/GB
,这意味着,用了 1KB
和用了 1GB
每月都要给 8 毛钱,而我基本每月只用 0.5GB
,那不如多编写几个 API 充分利用下吧。
创建 venv
因为腾讯云平台限定 Python3.6
执行环境,所以在进行以下操作前你应首先安装它,否则自定义依赖包后将无法运行。具体可搜索 操作系统+安装+Python3.6
,Linux 平台搜索 操作系统+编译安装+Python3.6
,本文不再赘述。
# 创建项目目录
mkdir api4scf
cd api4scf
# 安装 virtualenv
pip install virtualenv
# 创建 venv
virtualenv --python python3.6 --no-site-packages venv
# 激活 venv
source venv/bin/activate
搭建项目框架
整个项目目录结构如下,其中 api4scf/index.py
是入口文件,所有请求都将由它 分发
。api4scf/main
目录存放 业务及其依赖
,api4scf/test
存放 测试代码
,api4scf/venv
是 虚拟 python 环境
,上传代码时可以删除。
往下一层,api4scf/main/3rd
存放 自定义依赖包
,api4scf/main/api
存放 业务逻辑
。
api4scf
├── index.py
├── main
│ ├── 3rd
│ ├── api
│ └── __init__.py
├── test
└── venv
安装自定义依赖包
以二维码生成为例,使用 -t
参数,将 qrcode
包安装到 api4scf/main/3rd
下。如需其他依赖,也一并安装到该目录。
pip install -t ./main/3rd 'qrcode[pil]'
在 api4scf/main/__init__.py
文件中写入如下内容,意在将 3rd
文件夹加入 sys.path
,以便自定义依赖可以被解释器找到。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import sys
from os.path import abspath, join, dirname
sys.path.insert(0, join(abspath(dirname(__file__)), '3rd'))
编写业务逻辑
新建 api4scf/main/api/qrcode.py
文件,写入以下内容。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import qrcode
from io import BytesIO
from base64 import b64encode
def make_code(text, box_size, border_box):
"""二维码生成函数
Args:
text: 编码内容
box_size: 二维码所用方格数
border: 边框厚度所占方格数
Returns:
base64 格式图片
"""
qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=box_size,
border=border_box,
)
qr.add_data(text)
buffered = BytesIO()
qr.make_image().save(buffered, format='JPEG')
return 'data:image/jpg;base64,' + b64encode(buffered.getvalue()).decode('utf-8')
def door(queryString):
"""入口函数
Args:
queryString: 请求参数,包含
text: 编码内容,必须
size: 二维码所用方格数,可选
border: 边框厚度所占方格数,可选
Returns:
状态码,信息和 base64 图片数据,如
{
'code': 0,
'msg': 'success',
'qrcode': 'base64 图片数据'
}
"""
if 'text' not in queryString:
return {
'code': -1,
'error': '参数错误'
}
try:
text = queryString['text']
size = 12
border = 2
if 'size' in queryString:
size = queryString['size']
if 'border' in queryString:
border = queryString['border']
return {
'code': 0,
'msg': 'success',
'qrcode': make_code(text, size, border)
}
except Exception:
return {
'code': 1,
'error': '无法编码'
}
编写网关入口
在 api4scf/index.py
中写入如下代码,以便顺利接收和返回网关请求。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import json
try:
# SCF 环境
from main.api import qrcode
except Exception:
# 测试环境
from .main.api import qrcode
def gen_response(body):
"""返回网关指定格式
"""
return {
'isBase64Encoded': False,
'statusCode': 200,
'headers': {
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(body)
}
def check_path(real_path, expected_path):
"""检查 api 路径
"""
return real_path in ['/' + expected_path, '/' + expected_path + '/']
def router(event):
"""对多个 api 路径分发
"""
base = event['requestContext']['path']
path = event['path'].replace(base, '')
if check_path(path, 'qrcode'):
return qrcode.door(event['queryString'])
# elif check_path(path, 'aes'):
# return = aes.door(event['queryString'])
else:
return {
'code': -1,
'error': 'path error.'
}
def main_handler(event, context):
"""网关入口函数
"""
return gen_response(router(event))
编写测试代码
新建 api4scf/test/__init__.py
,内容为空,意在告诉解释器,test 文件夹是一个 module
。
新建 api4scf/test/scf.py
文件,写入如下代码,模拟 SCF 网关环境。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from ..index import main_handler
from urllib.parse import parse_qsl, urlparse
def split_url(url):
"""将 url 拆成路径和参数
"""
url_splited = urlparse(url)
return {
'path': url_splited.path,
'params': dict(parse_qsl(url_splited.query))
}
def request(url):
"""模拟 SCF 调用 main_handler
"""
url_splited = split_url(url)
event = {
'requestContext': {
'path': '/api4scf'
},
'path': url_splited['path'],
'queryString': url_splited['params']
}
print(main_handler(event, None))
print('--------------------------------')
接着,新建 api4scf/test/qrcode.py
文件,写入如下代码,请求虚拟 SCF,测试业务逻辑。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from .scf import request
request('/qrcode/')
request('/qrcode/?text=https://logi.im')
request('/qrcode/?text=https://logi.im&size=12&border=2')
最后运行如下命令测试,测试正常后便可将其部署至 SCF。
cd ..
python -m api4scf.test.qrcode
部署到腾讯云 SCF
由于之前写过两篇在腾讯云 SCF 部署 OneDrive 列表程序的文章,本文不再赘述。具体可参考 FODI,一款 OneDrive 秒级列表程序,只需阅读 创建函数服务
到 添加触发方式
章节间的内容,其他与本文无关。
如有问题请在下方留言,文章转载请注明出处,详细交流请加下方群组!请大佬不要屏蔽文中广告,因为它将帮我分担服务器开支,如果能帮忙点击我将万分感谢。