|
4 | 4 | import shutil |
5 | 5 | import tempfile |
6 | 6 | from typing import List, Optional |
| 7 | +from urllib.parse import urlsplit, urlunsplit |
7 | 8 |
|
8 | 9 | import requests |
9 | 10 | import uvicorn |
10 | 11 | from fastapi import Depends, FastAPI, HTTPException, Request, UploadFile |
11 | 12 | from fastapi.middleware.cors import CORSMiddleware |
12 | 13 | from sqlalchemy.orm import Session |
13 | | -from runtime_settings import get_allowed_origins |
| 14 | +from runtime_settings import ( |
| 15 | + get_allowed_origins, |
| 16 | + get_neuroglancer_public_base, |
| 17 | +) |
14 | 18 | from server_api.utils.io import readVol |
15 | 19 | from server_api.utils.utils import process_path |
16 | 20 | from server_api.auth import models, database, router as auth_router |
@@ -94,6 +98,42 @@ def _worker_url(path: str) -> str: |
94 | 98 | return f"{REACT_APP_SERVER_PROTOCOL}://{REACT_APP_SERVER_URL}{path}" |
95 | 99 |
|
96 | 100 |
|
| 101 | +def _derive_neuroglancer_public_base(request: Request) -> str: |
| 102 | + configured_base = get_neuroglancer_public_base() |
| 103 | + if configured_base: |
| 104 | + return configured_base |
| 105 | + |
| 106 | + forwarded_proto = request.headers.get("x-forwarded-proto") |
| 107 | + scheme = (forwarded_proto.split(",")[0].strip() if forwarded_proto else "") or ( |
| 108 | + request.url.scheme or "http" |
| 109 | + ) |
| 110 | + |
| 111 | + forwarded_host = request.headers.get("x-forwarded-host") |
| 112 | + request_host = ( |
| 113 | + forwarded_host.split(",")[0].strip() if forwarded_host else request.url.netloc |
| 114 | + ) |
| 115 | + hostname = request_host.split(":")[0] or "localhost" |
| 116 | + return f"{scheme}://{hostname}:4244" |
| 117 | + |
| 118 | + |
| 119 | +def _build_neuroglancer_public_url(viewer_url: str, request: Request) -> str: |
| 120 | + viewer_parts = urlsplit(viewer_url) |
| 121 | + base_parts = urlsplit(_derive_neuroglancer_public_base(request)) |
| 122 | + base_path = base_parts.path.rstrip("/") |
| 123 | + viewer_path = viewer_parts.path or "" |
| 124 | + combined_path = f"{base_path}{viewer_path}" if base_path else viewer_path |
| 125 | + |
| 126 | + return urlunsplit( |
| 127 | + ( |
| 128 | + base_parts.scheme or "http", |
| 129 | + base_parts.netloc, |
| 130 | + combined_path, |
| 131 | + viewer_parts.query, |
| 132 | + viewer_parts.fragment, |
| 133 | + ) |
| 134 | + ) |
| 135 | + |
| 136 | + |
97 | 137 | def _extract_upstream_payload(response: requests.Response): |
98 | 138 | try: |
99 | 139 | return response.json() |
@@ -394,8 +434,9 @@ def ngLayer(data, res, oo=[0, 0, 0], tt="segmentation"): |
394 | 434 | if gt is not None: |
395 | 435 | s.layers.append(name="gt", layer=ngLayer(gt, res, tt="segmentation")) |
396 | 436 |
|
397 | | - print(viewer) |
398 | | - return str(viewer) |
| 437 | + public_url = _build_neuroglancer_public_url(str(viewer), req) |
| 438 | + print(public_url) |
| 439 | + return public_url |
399 | 440 | finally: |
400 | 441 | for path in cleanup_paths: |
401 | 442 | try: |
|
0 commit comments