简体   繁体   English

将 fastapi 与 plotly.dash 结合并将令牌依赖项添加为身份验证的问题

[英]Problem with combining fastapi with plotly.dash and adding token dependency as auth

So this is an example dash app mounted to fastapi.所以这是一个安装到 fastapi 的示例 dash 应用程序。 I'm using app.mount based on this example from official docs fastapi-adcanced-wsgi .我正在使用 app.mount 基于官方文档fastapi-adcanced-wsgi中的这个示例。 Now I'm stuck because I don't see a way where I can mount this dash app and add fastapi dependency现在我被卡住了,因为我看不到可以挂载这个破折号应用程序并添加 fastapi 依赖项的方法

I would like to add a token or even basic auth to this dash sub app in way you add single dependency to fastapi routes:我想以向 fastapi 路由添加单个依赖项的方式向此破折号子应用程序添加令牌甚至基本身份验证:

from fastapi import Depends, FastAPI
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI()

security = HTTPBasic()


@app.get("/users/me")
def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
    return {"username": credentials.username, "password": credentials.password}

FastAPI example with working dash app. FastAPI 示例与工作破折号应用程序。

from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from datetime import datetime

# Create the Dash application, make sure to adjust requests_pathname_prefx
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app_dash = dash.Dash(__name__, external_stylesheets=external_stylesheets, requests_pathname_prefix='/dash/')

app_dash.layout = html.Div([
    html.Label('Dropdown'),
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),

    html.Label('Multi-Select Dropdown'),
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF'],
        multi=True
    ),

    html.Label('Radio Items'),
    dcc.RadioItems(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),

    html.Label('Checkboxes'),
    dcc.Checklist(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF']
    ),

    html.Label('Text Input'),
    dcc.Input(value='MTL', type='text'),

    html.Label('Slider'),
    dcc.Slider(
        min=0,
        max=9,
        marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
        value=5,
    ),
], style={'columnCount': 2})

# Now create your regular FASTAPI application

app = FastAPI()

@app.get("/hello_fastapi")
def read_main():
    return {"message": "Hello World"}

# Now mount you dash server into main fastapi application
app.mount("/dash", WSGIMiddleware(app_dash.server))

Not sure if it is possible to use the dependency with the WSGI sub-app, you might consider using middleware as a workaround.不确定是否可以将依赖项与 WSGI 子应用程序一起使用,您可以考虑使用中间件作为解决方法。 Something like this:像这样的东西:

from fastapi import FastAPI, Request
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask, escape, request
from starlette.responses import JSONResponse

flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "World")
    return f"Hello, {escape(name)} from Flask!"


app = FastAPI()


@app.middleware("http")
async def auth_middleware(request: Request, call_next):
    if (request.url.path.startswith("/v1") and
            request.headers.get('X-Token', None) != "expected_token"):
        return JSONResponse(status_code=403)
    response = await call_next(request)
    return response


@app.get("/v2")
def read_main():
    return {"message": "Hello World"}


app.mount("/v1", WSGIMiddleware(flask_app))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM