Commit 6a9bef75 authored by Timothy J. Baek's avatar Timothy J. Baek
Browse files

feat: backend reverse proxy

parent 611b10a7
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM node:alpine FROM node:alpine as build
WORKDIR /app
ARG OLLAMA_API_BASE_URL='' ARG OLLAMA_API_BASE_URL='/ollama/api'
RUN echo $OLLAMA_API_BASE_URL RUN echo $OLLAMA_API_BASE_URL
ENV ENV prod
ENV PUBLIC_API_BASE_URL $OLLAMA_API_BASE_URL ENV PUBLIC_API_BASE_URL $OLLAMA_API_BASE_URL
RUN echo $PUBLIC_API_BASE_URL RUN echo $PUBLIC_API_BASE_URL
WORKDIR /app
COPY package.json package-lock.json ./ COPY package.json package-lock.json ./
RUN npm ci RUN npm ci
COPY . . COPY . .
RUN npm run build RUN npm run build
CMD [ "npm", "run", "start"] FROM python:3.11-slim-buster as base
ARG OLLAMA_API_BASE_URL='/ollama/api'
ENV ENV=prod
ENV OLLAMA_API_BASE_URL $OLLAMA_API_BASE_URL
WORKDIR /app
COPY --from=build /app/build /app/build
WORKDIR /app/backend
COPY ./backend/requirements.txt ./requirements.txt
RUN pip3 install -r requirements.txt
COPY ./backend .
CMD [ "sh", "start.sh"]
\ No newline at end of file
__pycache__
.env
\ No newline at end of file
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)
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"
uvicorn main:app --port 8080 --reload
\ No newline at end of file
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")
fastapi
uvicorn[standard]
pydantic
python-multipart
flask
flask_cors
python-socketio
python-jose
passlib[bcrypt]
uuid
requests
pymongo
bcrypt
PyJWT
pyjwt[crypto]
\ No newline at end of file
uvicorn main:app --host 0.0.0.0 --port 8080
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "http-server ./build", "start": "http-server ./build -P http://localhost:8080?",
"dev": "vite dev --host", "dev": "vite dev --host",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
......
docker stop ollama-webui || true docker stop ollama-webui || true
docker rm ollama-webui || true docker rm ollama-webui || true
docker build -t ollama-webui . docker build -t ollama-webui .
docker run -d -p 3000:8080 --name ollama-webui --restart always ollama-webui docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway --name ollama-webui --restart always ollama-webui
docker image prune -f docker image prune -f
\ No newline at end of file
...@@ -2,4 +2,10 @@ ...@@ -2,4 +2,10 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
</script> </script>
<div>{$page.status}: {$page.error.message}</div> <div class=" bg-white dark:bg-gray-800 min-h-screen">
<div class=" flex h-full">
<div class="m-auto my-10 dark:text-gray-300 text-3xl font-semibold">
{$page.status}: {$page.error.message}
</div>
</div>
</div>
// if you want to generate a static html file // if you want to generate a static html file
// for your page. // for your page.
// Documentation: https://kit.svelte.dev/docs/page-options#prerender // Documentation: https://kit.svelte.dev/docs/page-options#prerender
export const prerender = true; // export const prerender = true;
// if you want to Generate a SPA // if you want to Generate a SPA
// you have to set ssr to false. // you have to set ssr to false.
// This is not the case (so set as true or comment the line) // This is not the case (so set as true or comment the line)
// Documentation: https://kit.svelte.dev/docs/page-options#ssr // Documentation: https://kit.svelte.dev/docs/page-options#ssr
// export const ssr = false; export const ssr = false;
// How to manage the trailing slashes in the URLs // How to manage the trailing slashes in the URLs
// the URL for about page witll be /about with 'ignore' (default) // the URL for about page witll be /about with 'ignore' (default)
......
...@@ -14,7 +14,7 @@ const config = { ...@@ -14,7 +14,7 @@ const config = {
adapter: adapter({ adapter: adapter({
pages: 'build', pages: 'build',
assets: 'build', assets: 'build',
fallback: null fallback: 'index.html'
}) })
} }
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment