MENU

腾讯云 SCF Python3.6 环境编写 RESTFUL API 指南

2019 年 12 月 08 日 • 阅读: 818 • 后端

之前已经 在腾讯云 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 秒级列表程序,只需阅读 创建函数服务添加触发方式 章节间的内容,其他与本文无关。

TG 大佬群 QQ 大佬群 QQ 追番群

返回文章列表 文章二维码
本页链接的二维码
打赏二维码
0:00