一日一技:FastAPI如何关闭接口文档?
摄影:产品经理
产品经理在七夕做的牛排
FastApi 自带的接口文档,让我们在开发后端接口的时候省了不少的工作量。它能自动根据你的代码识别接口的参数,还能根据你的注释生成接口的说明,如下图所示:
但问题来了,难道你上线的时候也把这个接口开放给外界?如下图所示:
重要接口的加密算法,就这么大摇大摆直接公开了,任何人只要在你的网址后面加上/docs
就能看到。如果老板知道了,可能你就得当场滚蛋了吧。
为了保住饭碗,我们必须在上线的时候,把文档接口关了。只有在开发测试的时候才能打开。
关闭部分接口
如何关闭部分接口?例如我做的这个服务,本身就是公共 API,就是拿给大家用的,只有几个核心接口隐藏一下,其他接口直接公开。
要隐藏部分接口,我们可以在路由装饰器上面添加一个参数include_in_schema=False
,如下图所示:
@app.post('/login', include_in_schema=False)
def login(params: LoginInfo):
"""
请求参数校验方案:
token = md5(username + password + 'kingnameisyourfather' + ts[3] + ts[8] + ts[15])
如果用户上传的 token 无法通过校验,则鉴权失败
"""
user_token = params.token
username = params.username
password = params.password
ts = params.ts
correct_token = hashlib.md5((username + password + 'kingnameisyourfather' + ts[3] + ts[8] + ts[15]).encode()).hexdigest()
if user_token != correct_token:
return {'success': False, 'msg': '反爬虫成功!'}
print('认证通过,开始进行后续处理')
...
return {'success': True, 'data': 'xxx'}
运行效果如下图所示:
可以看到,其他接口依然可以在文档中看到。但增加了这个排除参数的接口,已经从文档里面消失了。
关于include_in_schema
参数,可以参阅官方文档:Path Operation Advanced Configuration - FastAPI[1]
隐藏所有接口
如果你想把所有的接口全部关了怎么办呢?实际上也很简单,在初始化 FastApi 对象的时候,增加一个参数就可以了。
app = FastAPI(docs_url=None)
运行效果如下图所示:
好了,可以安心回家睡觉了——才怪。
FastAPI 实际上有两套文档系统,默认是同时开启的,我们刚刚只是关闭了其中一套。你试一试把/docs
改成/redoc
看看:
要关闭 redoc也可以使用相同的方法:
app = FastAPI(docs_url=None, redoc_url=None)
运行效果如下图所示:
关于这两个参数的更多详情,比如说保留文档,但是把网址改名,可以参阅官方文档:Metadata and Docs URLs - FastAPI[2]
如何自动切换
在开发阶段,我想要文档,在部署的时候,我不想要文档。难道每次都手动去改这几个参数?实际上不用,我们可以使用环境变量来自动控制,实现只有显式添加环境变量env=develop
的时候才显示文档,其他情况下都不显示。部分代码如下:
import os
from fastapi import FastAPI
env = os.getenv('env')
if env != 'develop':
app = FastAPI(docs_url=None, redoc_url=None)
else:
app = FastAPI()
当我们在自己电脑上开发的时候,我们在环境变量中添加一项env
,它的值为develop
,于是文档自动打开。当我们部署到线上环境的时候,把env
的值设置成prod
或者不设置,那么文档自动关闭。
参考资料
[1]
Path Operation Advanced Configuration - FastAPI: https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#exclude-from-openapi
[2]
Metadata and Docs URLs - FastAPI: https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls
- 困扰我多年的Connection reset问题
- scala学习笔记
- jersey处理支付宝异步回调通知的问题:java.lang.IllegalArgumentException: Error parsing media type 'application/x-www
- 使用 Java Service Wrapper 启动java后台进程服务
- PHP码农在Golang压力下的生存之道-PHP性能优化实践
- golang使用 mongo
- CoreOS Linux引入了Kubernetes kubelet
- gwt之mvc4g
- 来自1000多个项目的10大JavaScript错误浅析
- 编程思想 之「多态、初始化顺序、协变返回类型」
- 使用Golang语言执行shell文件
- Golang语言 Cookie的使用
- Golang语言-获取命令行参数
- GoldenGate复制的三个简单测试场景(r10笔记第83天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux配置实现免密钥登录过程解析
- 可以提高效率的十个Linux命令别名汇总
- 基于linux命令提取文件夹内特定文件路径
- Ubuntu20.04修改ip地址的方法示例
- Linux 逻辑卷管理(LVM)使用方法总结
- Linux 下载安装VSCode 使用编程输出当前时间的方法
- 详解Linux获取线程的PID(TID、LWP)的几种方式
- Linux文件基本属性知识点总结
- Linux MySQL忘记root密码解决方案
- 如何使用iostat查看linux硬盘IO性能
- linux搭建NFS文件共享服务器的步骤详解
- Windows和Linux实现远程桌面连接
- Ubuntu19.10开启ssh服务(详细过程)
- Ubuntu 18.04更换apt-get源的方法
- 浅谈Linux环境变量文件介绍