mirror of
https://github.com/KohakuBlueleaf/KohakuHub.git
synced 2026-03-09 07:12:07 -05:00
support cloudflare pages deployment
This commit is contained in:
5
functions/[[namespace]]/[[name]]/resolve/[[path]].js
Normal file
5
functions/[[namespace]]/[[name]]/resolve/[[path]].js
Normal file
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../../../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
5
functions/[[repo]].git/info/lfs/[[path]].js
Normal file
5
functions/[[repo]].git/info/lfs/[[path]].js
Normal file
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../../../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
13
functions/_middleware.js
Normal file
13
functions/_middleware.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Middleware that runs before all function routes
|
||||
* Useful for adding common headers like CORS
|
||||
*/
|
||||
export async function onRequest(context) {
|
||||
// Let route handlers run first
|
||||
const response = await context.next();
|
||||
|
||||
// Add common headers for all proxied responses
|
||||
response.headers.set('Access-Control-Allow-Credentials', 'true');
|
||||
|
||||
return response;
|
||||
}
|
||||
15
functions/_proxy.js
Normal file
15
functions/_proxy.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Shared proxy handler for KohakuHub API requests
|
||||
* Used by all Cloudflare Pages Functions to proxy requests to the backend API
|
||||
*/
|
||||
import { proxyToVps, handleOptions } from './_utils.js';
|
||||
|
||||
export async function proxyToAPI(context, stripPrefix) {
|
||||
// Handle CORS preflight
|
||||
if (context.request.method === 'OPTIONS') {
|
||||
return handleOptions(context.request);
|
||||
}
|
||||
|
||||
// Proxy to VPS API
|
||||
return proxyToVps(context.request, context.env, stripPrefix);
|
||||
}
|
||||
67
functions/_utils.js
Normal file
67
functions/_utils.js
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Shared utilities for KohakuHub Cloudflare Pages Functions
|
||||
*/
|
||||
|
||||
// VPS API origin - override with environment variable
|
||||
export const getApiOrigin = (env) => env.API_BASE_URL || 'http://hub-api:48888';
|
||||
|
||||
/**
|
||||
* Proxy request to VPS API server
|
||||
* @param {Request} request - Original request
|
||||
* @param {object} env - Environment variables
|
||||
* @param {string} stripPrefix - Optional prefix to strip from path (e.g., '/api')
|
||||
* @returns {Promise<Response>}
|
||||
*/
|
||||
export async function proxyToVps(request, env, stripPrefix) {
|
||||
const inUrl = new URL(request.url);
|
||||
const outUrl = new URL(getApiOrigin(env));
|
||||
|
||||
// Keep path, optionally strip a prefix like "/api"
|
||||
const path = stripPrefix
|
||||
? inUrl.pathname.replace(new RegExp(`^${stripPrefix}`), '')
|
||||
: inUrl.pathname;
|
||||
|
||||
outUrl.pathname = path;
|
||||
outUrl.search = inUrl.search;
|
||||
|
||||
// Pass request through (streams upload/download)
|
||||
const resp = await fetch(outUrl.toString(), {
|
||||
method: request.method,
|
||||
headers: request.headers,
|
||||
body: request.body,
|
||||
duplex: 'half', // Required for streaming request bodies
|
||||
});
|
||||
|
||||
// Adjust headers for browser compatibility
|
||||
const headers = new Headers(resp.headers);
|
||||
|
||||
// Allow same-origin SPA to read responses
|
||||
headers.set('Access-Control-Allow-Origin', inUrl.origin);
|
||||
headers.set('Access-Control-Allow-Credentials', 'true');
|
||||
|
||||
return new Response(resp.body, {
|
||||
status: resp.status,
|
||||
statusText: resp.statusText,
|
||||
headers: headers,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle CORS preflight requests
|
||||
* @param {Request} request - Original request
|
||||
* @returns {Response}
|
||||
*/
|
||||
export function handleOptions(request) {
|
||||
const reqHeaders = request.headers.get('Access-Control-Request-Headers') || 'content-type, authorization';
|
||||
const reqMethod = request.headers.get('Access-Control-Request-Method') || 'GET,POST,PUT,PATCH,DELETE,OPTIONS';
|
||||
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': reqMethod,
|
||||
'Access-Control-Allow-Headers': reqHeaders,
|
||||
'Access-Control-Max-Age': '86400',
|
||||
},
|
||||
});
|
||||
}
|
||||
7
functions/api/[[path]].js
Normal file
7
functions/api/[[path]].js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { proxyToAPI } from '../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
// Strip /api prefix if your backend doesn't expect it
|
||||
// Remove the second parameter if your backend expects /api in the path
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../../../../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../../../../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
5
functions/org/[[path]].js
Normal file
5
functions/org/[[path]].js
Normal file
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { proxyToAPI } from '../../../../_proxy.js';
|
||||
|
||||
export async function onRequest(context) {
|
||||
return proxyToAPI(context);
|
||||
}
|
||||
13
src/kohaku-hub-ui/public/_routes.json
Normal file
13
src/kohaku-hub-ui/public/_routes.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"include": [
|
||||
"/api/*",
|
||||
"/org/*",
|
||||
"/*.git/info/lfs/*",
|
||||
"/models/*/*/resolve/*",
|
||||
"/datasets/*/*/resolve/*",
|
||||
"/spaces/*/*/resolve/*",
|
||||
"/*/*/resolve/*"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
||||
Reference in New Issue
Block a user