有问题的设置如下所示:
我的网络应用程序使用和工作类fastapi实现和部署,位于具有IP地址的同一主机上的代理后面(以及其他远程设备后面,例如VPN集中器等)gunicornuvicornnginx172.31.x.x
nginx配置如下:
location / {
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from 172.31.x.x/32; # well-known vpn concentrator
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://172.31.x.x:5045;
Run Code Online (Sandbox Code Playgroud)
gunicorn配置如下:
OPTIONS="--bind 127.0.0.1:5045 --bind 172.31.x.x:5045 --forwarded-allow-ips=127.0.0.1,172.31.x.x --workers 1 --worker-class uvicorn.workers.Uv
icornWorker --log-config config/logging.conf"
Run Code Online (Sandbox Code Playgroud)
在fastapi使用starlette.requests.Request对象(名为request)时,request.client.host打印托管 Web 应用程序的服务器的接口 IP 地址(即172.31.x.x)
request.headers["x-real-ip"], request.headers["x-forwarded-for"]两者都打印我的代理之前设备的 IP 地址,这是我公司中众所周知的防火墙设备。
我想问的是:
X-Forwarded-ForHTTP 标头来查看中间代理服务?我正在尝试在 fastapi 中间件中验证令牌,但这似乎是不可能的。因为我认为中间件需要进行下一次调用,尽管它不是必需的。我无法在这个 python-fastapi 后端找到任何好的解决方案来一次性处理令牌。任何帮助表示赞赏。
@app.middleware("http")
async def add_middleware_here(request: Request, call_next):
token = request.headers["Authorization"]
try:
verification_of_token = verify_token(token)
if verification_of_token:
response = await call_next(request)
return response
except InvalidSignatureError as er:
raise HTTPException(status_code=401)
Run Code Online (Sandbox Code Playgroud) 按照uvicorn-gunicorn-fastapi-docker中的文档,我应该通过运行以下命令来运行我的图像:
docker run -d -p 80:80 -v $(pwd):/app myimage /start-reload.sh
Run Code Online (Sandbox Code Playgroud)
但我得到:
Usage: uvicorn [OPTIONS]
Try 'uvicorn --help' for help.
Error: Got unexpected extra argument (/start-reload.sh)
Run Code Online (Sandbox Code Playgroud)
我成功地使用我在这里找到的调试模式挂载了一个卷?但我认为它不够优雅,每次进行更改时我都必须运行它(至少我不必构建图像)
docker run --name ${containerName} \
--env GUNICORN_CMD_ARGS="--reload" \
-p 5000:5000 \
-v $(pwd)/app:/app \
${imageName}:${versionTag}
Run Code Online (Sandbox Code Playgroud)
我的 Dockerfile 只是:
FROM tiangolo/uvicorn-gunicorn-fastapi:latest
EXPOSE 5000
COPY ./app /app
ENTRYPOINT ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5000"]
Run Code Online (Sandbox Code Playgroud)
它按预期工作。
当我更改代码时可以重新加载吗?
我有一个简单的Uvicorn应用程序(使用FastAPI构建)。开发中,uvicorn server:app --reload。该--reload参数表示将启动两个线程,一个用于服务器,一个用于监视文件更改\xe2\x80\x94当检测到文件更改时,将重新启动服务器线程。
到目前为止没有什么特别的。这在 Flask、Django 和其他开发服务器中也很常见。问题是,我想pyngrok在启动开发服务器时使用打开一个隧道,并且我希望该隧道与这两个线程的父线程一样长寿。也就是说,当检测到文件更改并重新启动开发服务器时,我不希望重新启动隧道(因为ngrok这会导致生成新的公共 URL 并中断现有连接)。
使用 Flask 和 Django,这相对容易完成。例如,对于 Flask,我只是这样做os.environ.get("WERKZEUG_RUN_MAIN") != "true",对于 Django,我类似地评估RUN_MAIN环境变量,并且在任何一种情况下,我仅在将这些设置为 时才实例化隧道true。我找不到与 Uvicorn 一起使用的类似变量。有人可以帮忙吗?
我一直在尝试从 daphne 切换到 uvicorn 进行使用 django 3 和通道的项目的生产。我在加载频道的经典 asgi 文件时遇到错误。由于同步调用 django.setup 或 get_application,我无法使用它。我尝试使用sync_to_async 调用调整此文件,但没有成功。有人设法让它发挥作用吗?
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
django.setup()
application = get_default_application()
Run Code Online (Sandbox Code Playgroud)
Traceback (most recent call last):
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/var/www/.cache/pypoetry/virtualenvs/project-4ffvdAoS-py3.8/lib/python3.8/site-packages/uvicorn/subprocess.py", line 61, in subprocess_started
target(sockets=sockets)
File "/var/www/.cache/pypoetry/virtualenvs/project-4ffvdAoS-py3.8/lib/python3.8/site-packages/uvicorn/main.py", line 407, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 612, in run_until_complete
return future.result()
File "/var/www/.cache/pypoetry/virtualenvs/project-4ffvdAoS-py3.8/lib/python3.8/site-packages/uvicorn/main.py", line 414, in serve
config.load() …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用请求将 JSON 数据+文件(二进制)上传到 FastAPI“POST”端点。
这是服务器代码:
@app.post("/files/")
async def create_file(
file: bytes = File(...), fileb: UploadFile = File(...), timestamp: str = Form(...)
):
return {
"file_size": len(file),
"timestamp": timestamp,
"fileb_content_type": fileb.content_type,
}
Run Code Online (Sandbox Code Playgroud)
这是客户端代码:
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(max_retries=0)
session.mount('http://', adapter)
jpg_image = open(IMG_PATH, 'rb').read()
timestamp_str = datetime.datetime.now().isoformat()
files = {
'timestamp': (None, timestamp_str),
'file': ('image.jpg', jpg_image),
}
request = requests.Request('POST',
FILE_UPLOAD_ENDPOINT,
files=files)
prepared_request = request.prepare()
response = session.send(prepared_request)
Run Code Online (Sandbox Code Playgroud)
服务器失败并显示
“POST /files/ HTTP/1.1” 422 无法处理的实体
我正在使用 uvicorn 和 python 的 subprocess.Popen 运行多个 FastAPI 实例。我有一个用 PySimpleGUI 制作的小型 GUI,我希望能够随意关闭服务器并重新启动它们。
我遇到的第一个问题是,至少在 Windows 中,启动 uvicorn 服务器似乎创建的不是一个,而是两个新进程,并且调用Popen.terminate()仅关闭其中一个进程,这不会释放与服务器关联的端口。我使用 psutil 包修复了此问题,以检查实例化 Popen 对象后创建了哪些新进程,并使用 psutil 跟踪和终止第二个进程。
还有一个主要问题是,调用psutil.terminate()进程并没有调用.net下的FastAPI函数@app.on_event("shutdown")。过去,我们在单独的终端窗口中运行所有服务器,并发现这些终端窗口上的 ctrl-c 将调用关闭事件,但我没有找到其他方法来执行此操作。我界面上的 ctrl-c 显然会关闭界面和所有服务器,并且在命中所有服务器的关闭事件方面有些不可靠。我的另一个想法是 use psutil.send_signal(signal.CTRL_C_EVENT),但这与在终端中调用 ctrl-c 具有相同的效果。
所以我很茫然。我看到很多帖子说这是 uvicorn 的普遍缺点,但没有看到任何直接证实我自己的经验或提供解决方案的内容。我还知道 FastAPI 中的“关闭”和“启动”事件是从 Starlette 移植的,并且在这两个包中都没有很好的记录。我看到过使用 guvicorn 的建议,但我的简短调查证实它与 Windows 不兼容。有什么建议么?
我在使用aiogram和Fastapi时遇到fsm问题。我运行了aiogram_fsm_example中的代码,但将长轮询更改为 Fastapi 实现。这是我得到的代码:
import logging
from fastapi import FastAPI, Request
import aiogram.utils.markdown as md
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types import ParseMode
from aiogram.utils import executor
logging.basicConfig(level=logging.INFO)
API_TOKEN = "here's the bot token"
bot = Bot(token=API_TOKEN)
# For example use simple MemoryStorage for Dispatcher.
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
# States
class …Run Code Online (Sandbox Code Playgroud) 我有一个小型的测试 FastAPI Web 应用程序,它提供一个简单的 HTML 页面,该页面需要位于静态文件夹中的 css 样式表。它安装在 Linode 服务器(Ubuntu 20.04 LTS)、nginx、gunicorn、uvicorn 工作人员和supervisorctl 上。我已经使用 certbot 添加了证书。
该应用程序在 http 中工作正常,但无法访问 https 中的静态文件。当通过 http 访问时,所有基于静态的功能都可以工作,但是当通过 https 访问时,它缺少 css 样式表中的所有样式。我需要让它工作,这样我就可以加载一个需要 css 和其他静态文件夹存储功能的更复杂的应用程序。
文件结构为:
/home/<user_name>/application
- main.py
- static
|_ css
|_ bootstrap
- templates
|_ index.html
Run Code Online (Sandbox Code Playgroud)
主要.py:
import fastapi
import uvicorn
from fastapi import Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
api = fastapi.FastAPI()
api.mount('/static', StaticFiles(directory='static'), name='static')
templates = Jinja2Templates(directory="templates")
@api.get('/')
@api.get('/index', response_class=HTMLResponse)
def index(request: Request):
message …Run Code Online (Sandbox Code Playgroud) 如果我向此 API 发送请求:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Response(BaseModel):
var_name: str
@app.put("/", response_model=Response)
def simple_server(a: str):
response = Response(var_name=a)
return response
Run Code Online (Sandbox Code Playgroud)
我收到此 json 文件的响应{"var_name1": "a"}。此外,我还得到了一个非常漂亮的 Swagger UI,它说明了响应字段。
我的问题是,如何{"var-name1": "a"}在 Swagger 文档中使用同样好的输入方式获取这个 json 文件(这是用连字符而不是下划线)?
显然,我无法命名响应数据类中的var_name属性var-name。