Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,19 @@ services:
# installation commands; it is never passed as a build ARG.
secrets:
- github_token
# ragbio-ui (the frontend built by the ui-builder stage, which the
# `backend` target still depends on and COPYs dist/ from -- see the
# Dockerfile) bakes this in as import.meta.env.VITE_RAGBIO_API_KEY at
# build time (Vite env vars are compile-time, not runtime -- setting
# RAGBIO_API_KEY under `environment:` below only reaches the running
# backend process, never the already-built frontend bundle). Without
# this build arg the Dockerfile's `ARG RAGBIO_API_KEY` stays empty
# regardless of what .env holds, so every ragbio-ui request sends a
# literal "Authorization: Bearer undefined" and the backend correctly
# (if unhelpfully) reports "Not authenticated" -- confirmed missing
# here, not an nginx routing gap.
args:
RAGBIO_API_KEY: ${RAGBIO_API_KEY}
restart: on-failure
# image: ghcr.io/omnibioai/omnibioai-rag:latest
# Frontend served at http://localhost:8090/ via nginx (port 5175 inside container)
Expand Down
20 changes: 14 additions & 6 deletions docker/nginx-router.conf
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,15 @@ server {
index index.html;
autoindex off;
}
location ^~ /_svc/workbench { rewrite ^/_svc/workbench(/.*)$ $1 break; set $workbench_upstream workbench:8000; proxy_pass http://$workbench_upstream; }
# NOTE: `set` must come BEFORE `rewrite ... break;`, not after -- `break`
# stops processing of the *entire* current set of ngx_http_rewrite_module
# directives (that's `set` too, not just `rewrite`/`if`), so a `set`
# written after it in the same location never runs. Got this backwards
# on the first pass: `rewrite ...; set $x ...; proxy_pass http://$x;`
# silently left $workbench_upstream (and five siblings below) permanently
# empty -- "using uninitialized ... variable" / "invalid URL prefix in
# http://" / 500, confirmed live in the error log.
location ^~ /_svc/workbench { set $workbench_upstream workbench:8000; rewrite ^/_svc/workbench(/.*)$ $1 break; proxy_pass http://$workbench_upstream; }
location ^~ /_svc/lims {
# NOTE: this location defines its own proxy_set_header directives, which means
# none of the server-level ones above are inherited (nginx behavior: a location
Expand All @@ -281,8 +289,8 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $router_xfp;
rewrite ^/_svc/lims(/.*)$ $1 break;
set $lims_upstream lims:7000;
rewrite ^/_svc/lims(/.*)$ $1 break;
proxy_pass http://$lims_upstream;
}
# LIMS's session login (django.contrib.auth's LoginView/LogoutView,
Expand Down Expand Up @@ -508,8 +516,8 @@ server {
location ^~ /_svc/toolserver { rewrite ^/_svc/toolserver(/.*)$ $1 break; proxy_pass http://toolserver; }
location ^~ /_svc/auth {
limit_req zone=auth_limit burst=5 nodelay;
rewrite ^/_svc/auth(/.*)$ $1 break;
set $auth_upstream auth-service:8001;
rewrite ^/_svc/auth(/.*)$ $1 break;
proxy_pass http://$auth_upstream;
}
# Bare /auth/* — OAuth2 login/callback redirect targets registered with
Expand Down Expand Up @@ -544,8 +552,8 @@ server {
# /api/license/* traffic.
location ^~ /api/license/ {
limit_req zone=auth_limit burst=5 nodelay;
rewrite ^/api/license(/.*)$ $1 break;
set $auth_upstream auth-service:8001;
rewrite ^/api/license(/.*)$ $1 break;
proxy_pass http://$auth_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
Expand Down Expand Up @@ -704,16 +712,16 @@ server {
location ^~ /ops/ { set $workbench_upstream workbench:8000; proxy_pass http://$workbench_upstream; }
location ^~ /plugins/ { set $workbench_upstream workbench:8000; proxy_pass http://$workbench_upstream; }
location ^~ /_svc/policy {
rewrite ^/_svc/policy/?(.*)$ /$1 break;
set $policy_upstream policy-engine:8002;
rewrite ^/_svc/policy/?(.*)$ /$1 break;
proxy_pass http://$policy_upstream;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
}
location ^~ /_svc/hpc {
rewrite ^/_svc/hpc/?(.*)$ /$1 break;
set $hpc_upstream hpc-policy-engine:8003;
rewrite ^/_svc/hpc/?(.*)$ /$1 break;
proxy_pass http://$hpc_upstream;
proxy_http_version 1.1;
proxy_set_header Connection "";
Expand Down
14 changes: 12 additions & 2 deletions src/ui/pages/Jobs.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback, useRef } from "react";
import { isElectron } from "../lib/session";
import { isElectron, getToken } from "../lib/session";

function getHost() {
return (
Expand All @@ -18,9 +18,19 @@ function tesUrl(path) {
}

async function apiFetch(path, opts = {}) {
// TES's own auth middleware requires a bearer token ({"detail":"missing
// bearer token"} on :8081) -- this fetch() is a normal same-origin XHR,
// not an iframe navigation (unlike RAG/Control Center), so it's fully
// able to attach a real header itself instead of relying on nginx to
// synthesize one from a cookie. Same pattern as rolesApi.js's request().
const token = getToken();
const res = await fetch(tesUrl(path), {
...opts,
headers: { "Content-Type": "application/json", ...(opts.headers || {}) },
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts.headers || {}),
},
signal: opts.signal || AbortSignal.timeout(10000),
});
if (!res.ok) {
Expand Down
Loading