Ollama-kutsut hubin kautta: ei mixed content HTTPS-sivulla
Lisätty GET /api/v1/ollama/tags proxy-endpoint hubiin. Poistettu suorat http://hostname:11434 -kutsut frontendistä. Hub välittää Ollama-kutsut sisäisessä Docker-verkossa. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,3 +16,4 @@ futures = "0.3"
|
|||||||
rusqlite = { version = "0.31", features = ["bundled"] }
|
rusqlite = { version = "0.31", features = ["bundled"] }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ async fn main() {
|
|||||||
.route("/api/v1/chat/completions", axum::routing::post(api_chat_completions))
|
.route("/api/v1/chat/completions", axum::routing::post(api_chat_completions))
|
||||||
.route("/api/v1/model", axum::routing::post(api_change_model))
|
.route("/api/v1/model", axum::routing::post(api_change_model))
|
||||||
.route("/api/v1/hardware", get(api_hardware))
|
.route("/api/v1/hardware", get(api_hardware))
|
||||||
|
.route("/api/v1/ollama/tags", get(api_ollama_tags))
|
||||||
.route("/admin", get(admin_page))
|
.route("/admin", get(admin_page))
|
||||||
.nest_service("/", {
|
.nest_service("/", {
|
||||||
let static_dir = std::env::var("STATIC_DIR").unwrap_or_else(|_| "../static".to_string());
|
let static_dir = std::env::var("STATIC_DIR").unwrap_or_else(|_| "../static".to_string());
|
||||||
@@ -960,6 +961,20 @@ struct ChatCompletionResponse {
|
|||||||
tokens_generated: u64,
|
tokens_generated: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn api_ollama_tags() -> axum::response::Response {
|
||||||
|
let ollama_url = std::env::var("OLLAMA_URL").unwrap_or_else(|_| "http://ollama:11434".to_string());
|
||||||
|
match reqwest::get(format!("{}/api/tags", ollama_url)).await {
|
||||||
|
Ok(resp) => {
|
||||||
|
if let Ok(body) = resp.json::<serde_json::Value>().await {
|
||||||
|
axum::Json(body).into_response()
|
||||||
|
} else {
|
||||||
|
axum::Json(serde_json::json!({ "models": [] })).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => axum::Json(serde_json::json!({ "models": [] })).into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn api_hardware(
|
async fn api_hardware(
|
||||||
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
|
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
|
||||||
) -> axum::response::Response {
|
) -> axum::response::Response {
|
||||||
|
|||||||
@@ -2830,19 +2830,11 @@ ${generatedFiles['Dockerfile'] || '(puuttuu)'}`;
|
|||||||
if (content) content.textContent = spinFrames[spinIdx] + ' Ladataan ' + selected.name + '...';
|
if (content) content.textContent = spinFrames[spinIdx] + ' Ladataan ' + selected.name + '...';
|
||||||
}, 100);
|
}, 100);
|
||||||
// Vaihdetaan malli hubille + Ollama pull
|
// Vaihdetaan malli hubille + Ollama pull
|
||||||
Promise.all([
|
fetch('/api/v1/model', {
|
||||||
fetch('/api/v1/model', {
|
method: 'POST',
|
||||||
method: 'POST',
|
headers: { 'Content-Type': 'application/json' },
|
||||||
headers: { 'Content-Type': 'application/json' },
|
body: JSON.stringify({ model: selected.name }),
|
||||||
body: JSON.stringify({ model: selected.name }),
|
}).then(r => r.json()).then(hubData => {
|
||||||
}).then(r => r.json()),
|
|
||||||
// Suora pull Ollamasta — odotetaan kunnes malli on ladattu
|
|
||||||
fetch('http://' + window.location.hostname + ':11434/api/pull', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ name: selected.name, stream: false }),
|
|
||||||
}).then(r => r.json()).catch(() => ({ status: 'ok' })),
|
|
||||||
]).then(([hubData, _]) => {
|
|
||||||
clearInterval(spinTimer);
|
clearInterval(spinTimer);
|
||||||
pullLine.remove();
|
pullLine.remove();
|
||||||
if (hubData.status === 'ok') {
|
if (hubData.status === 'ok') {
|
||||||
@@ -2878,7 +2870,7 @@ ${generatedFiles['Dockerfile'] || '(puuttuu)'}`;
|
|||||||
// Haetaan ladatut mallit Ollamasta
|
// Haetaan ladatut mallit Ollamasta
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fetch('/api/v1/hardware').then(r => r.json()).catch(() => ({})),
|
fetch('/api/v1/hardware').then(r => r.json()).catch(() => ({})),
|
||||||
fetch('http://' + window.location.hostname + ':11434/api/tags').then(r => r.json()).catch(() => ({ models: [] })),
|
fetch('/api/v1/ollama/tags').then(r => r.json()).catch(() => ({ models: [] })),
|
||||||
]).then(([hw, ollama]) => {
|
]).then(([hw, ollama]) => {
|
||||||
const loadedNames = (ollama.models || []).map(m => m.name.replace(':latest', ''));
|
const loadedNames = (ollama.models || []).map(m => m.name.replace(':latest', ''));
|
||||||
const btn = document.getElementById('agent-compute-btn');
|
const btn = document.getElementById('agent-compute-btn');
|
||||||
|
|||||||
Reference in New Issue
Block a user