forked from open-webui/open-webui
feat: backend reverse proxy
This commit is contained in:
parent
611b10a79d
commit
6a9bef755b
13 changed files with 179 additions and 13 deletions
2
backend/.gitignore
vendored
Normal file
2
backend/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
__pycache__
|
||||
.env
|
55
backend/apps/ollama/main.py
Normal file
55
backend/apps/ollama/main.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
from flask import Flask, request, Response
|
||||
from flask_cors import CORS
|
||||
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
from config import OLLAMA_API_BASE_URL
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(
|
||||
app
|
||||
) # Enable Cross-Origin Resource Sharing (CORS) to allow requests from different domains
|
||||
|
||||
# Define the target server URL
|
||||
TARGET_SERVER_URL = OLLAMA_API_BASE_URL
|
||||
|
||||
|
||||
@app.route("/", defaults={"path": ""}, methods=["GET", "POST", "PUT", "DELETE"])
|
||||
@app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE"])
|
||||
def proxy(path):
|
||||
# Combine the base URL of the target server with the requested path
|
||||
target_url = f"{TARGET_SERVER_URL}/{path}"
|
||||
print(target_url)
|
||||
|
||||
# Get data from the original request
|
||||
data = request.get_data()
|
||||
headers = dict(request.headers)
|
||||
|
||||
# Make a request to the target server
|
||||
target_response = requests.request(
|
||||
method=request.method,
|
||||
url=target_url,
|
||||
data=data,
|
||||
headers=headers,
|
||||
stream=True, # Enable streaming for server-sent events
|
||||
)
|
||||
|
||||
# Proxy the target server's response to the client
|
||||
def generate():
|
||||
for chunk in target_response.iter_content(chunk_size=8192):
|
||||
yield chunk
|
||||
|
||||
response = Response(generate(), status=target_response.status_code)
|
||||
|
||||
# Copy headers from the target server's response to the client's response
|
||||
for key, value in target_response.headers.items():
|
||||
response.headers[key] = value
|
||||
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
15
backend/config.py
Normal file
15
backend/config.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import sys
|
||||
import os
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
|
||||
load_dotenv(find_dotenv())
|
||||
|
||||
ENV = os.environ.get("ENV", "dev")
|
||||
|
||||
OLLAMA_API_BASE_URL = os.environ.get(
|
||||
"OLLAMA_API_BASE_URL", "http://localhost:11434/api"
|
||||
)
|
||||
|
||||
if ENV == "prod":
|
||||
if OLLAMA_API_BASE_URL == "/ollama/api":
|
||||
OLLAMA_API_BASE_URL = "http://host.docker.internal:11434/api"
|
1
backend/dev.sh
Normal file
1
backend/dev.sh
Normal file
|
@ -0,0 +1 @@
|
|||
uvicorn main:app --port 8080 --reload
|
51
backend/main.py
Normal file
51
backend/main.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import time
|
||||
import sys
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from fastapi import HTTPException
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
|
||||
from fastapi.middleware.wsgi import WSGIMiddleware
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from apps.ollama.main import app as ollama_app
|
||||
|
||||
|
||||
class SPAStaticFiles(StaticFiles):
|
||||
async def get_response(self, path: str, scope):
|
||||
try:
|
||||
return await super().get_response(path, scope)
|
||||
except (HTTPException, StarletteHTTPException) as ex:
|
||||
if ex.status_code == 404:
|
||||
return await super().get_response("index.html", scope)
|
||||
else:
|
||||
raise ex
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
origins = ["*"]
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def check_url(request: Request, call_next):
|
||||
start_time = int(time.time())
|
||||
response = await call_next(request)
|
||||
process_time = int(time.time()) - start_time
|
||||
response.headers["X-Process-Time"] = str(process_time)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
app.mount("/ollama/api", WSGIMiddleware(ollama_app))
|
||||
app.mount("/", SPAStaticFiles(directory="../build", html=True), name="spa-static-files")
|
19
backend/requirements.txt
Normal file
19
backend/requirements.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
fastapi
|
||||
uvicorn[standard]
|
||||
pydantic
|
||||
python-multipart
|
||||
|
||||
flask
|
||||
flask_cors
|
||||
|
||||
python-socketio
|
||||
python-jose
|
||||
passlib[bcrypt]
|
||||
uuid
|
||||
|
||||
requests
|
||||
pymongo
|
||||
bcrypt
|
||||
|
||||
PyJWT
|
||||
pyjwt[crypto]
|
1
backend/start.sh
Normal file
1
backend/start.sh
Normal file
|
@ -0,0 +1 @@
|
|||
uvicorn main:app --host 0.0.0.0 --port 8080
|
Loading…
Add table
Add a link
Reference in a new issue