How GeoLibre Builds Proxy Requests to the Python Sidecar at /sidecar

GeoLibre resolves the sidecar base URL at runtime using resolveSidecarBaseUrl() in packages/processing/src/sidecar-client.ts, choosing between a local development URL (http://127.0.0.1:8765) or a same-origin proxy path (/sidecar) based on the current protocol, port, and environment.

GeoLibre's browser-based interface needs to communicate with its Python sidecar for geoprocessing tasks—health checks, Whitebox tools, and vector/raster conversions. Rather than hard-coding host and port combinations, the frontend dynamically constructs request URLs. This approach lets the same codebase run in Vite development, Docker deployments, and the native Tauri desktop app without configuration changes.

How the Base URL Is Determined

The function resolveSidecarBaseUrl() in packages/processing/src/sidecar-client.ts implements a cascading decision tree to pick the correct sidecar endpoint.

// packages/processing/src/sidecar-client.ts
function resolveSidecarBaseUrl(): string {
  const override = explicitSidecarUrl();            // VITE_SIDECAR_URL env var
  if (override) return override;

  // When running in a non‑browser context (e.g. during CI) use the local sidecar.
  if (typeof window === "undefined" || !window.location) {
    return LOCAL_SIDECAR_URL;                      // "http://127.0.0.1:8765"
  }

  const { protocol, hostname, port, origin } = window.location;
  const isTauri = protocol === "tauri:" || hostname === "tauri.localhost";
  const isViteDev = port === "5173";

  // Production or Docker builds are served from an http(s) origin.
  // In those cases the sidecar is reachable via a **same‑origin reverse proxy**
  // that maps "/sidecar" to the real sidecar process, avoiding CORS.
  if (!isTauri && !isViteDev && (protocol === "http:" || protocol === "https:")) {
    return `${origin}/sidecar`;
  }

  // Fallback to the local dev sidecar.
  return LOCAL_SIDECAR_URL;
}

The function evaluates three conditions in priority order:

  • Explicit override — If VITE_SIDECAR_URL is set, use that value directly.
  • Tauri desktop or Vite dev server — When protocol === "tauri:" or port === "5173", connect to LOCAL_SIDECAR_URL (http://127.0.0.1:8765).
  • Docker or production HTTP(S) origin — Use ${origin}/sidecar to leverage same-origin reverse proxying, eliminating CORS requirements.

The result is cached in DEFAULT_SIDECAR_URL and used for all subsequent sidecar API calls.

How Requests Are Sent with sidecarFetch

Every sidecar operation flows through a thin wrapper that handles authentication token injection:

function sidecarFetch(input: string, init?: RequestInit): Promise<Response> {
  if (!sidecarAuthToken) return fetch(input, init); // desktop injects token via nginx
  const headers = new Headers(init?.headers);
  headers.set("X-GeoLibre-Token", sidecarAuthToken);
  return fetch(input, { ...init, headers });
}
  • Browser/Docker builds: sidecarAuthToken is null, so requests pass through unmodified.
  • Tauri desktop builds: The Tauri shell generates a token and injects it via nginx; sidecarFetch adds the X-GeoLibre-Token header.

A typical health check implementation demonstrates the pattern:

export async function checkSidecarHealth(): Promise<SidecarHealth> {
  const res = await sidecarFetch(`${DEFAULT_SIDECAR_URL}/health`);
  if (!res.ok) throw new Error("Sidecar health check failed");
  return res.json();
}

All endpoints—/algorithms, /whitebox/*, /vector/*, /raster/*—follow this same construction pattern.

Server-Side Proxy Configuration

GeoLibre ensures /sidecar requests never trigger the SPA router:

// apps/geolibre-desktop/vite.config.ts (excerpt)
navigateFallbackDenylist: [/^\/sidecar\//, /^\/__geolibre_/, /\/[^/?]+\.[^/]+$/],

Two proxy layers handle the actual forwarding:

Environment Implementation Behavior
Vite dev server vite-proxy-guard.ts middleware Forwards /sidecar/* to the running FastAPI dev server or Docker sidecar container
Production/Docker nginx reverse proxy Maps /sidecar/* to 127.0.0.1:8765 with automatic token injection for desktop builds

This architecture guarantees same-origin requests in production, avoiding CORS preflight overhead and complexity.

Complete Request Flow

  1. UI code imports from @geolibre/processing and calls a sidecar function.
  2. resolveSidecarBaseUrl() evaluates window.location to choose between local development URL or /sidecar proxy path.
  3. The endpoint path (e.g., /whitebox/tools) is appended to the base URL.
  4. sidecarFetch executes fetch, adding the auth token only in Tauri desktop builds.
  5. Vite middleware or nginx routes the request to the Python FastAPI sidecar.

Practical Code Examples

Health Check on Application Startup

import { checkSidecarHealth } from "@geolibre/processing";

async function ensureSidecar() {
  try {
    const { status } = await checkSidecarHealth();
    console.log("Sidecar status:", status);
  } catch (e) {
    console.error("Sidecar unreachable:", e);
  }
}

Executing a Whitebox Tool

import { runWhiteboxTool } from "@geolibre/processing";

async function hillshade(input: string, output: string) {
  const jobId = await runWhiteboxTool("hillshade", {
    inputs: [{ name: "dem", path: input }],
    outputs: [{ name: "output", path: output }],
  });
  // Poll job status, retrieve results...
}

Both examples automatically use the correct base URL without caller awareness of the deployment context.

Key Source Files

File Purpose
packages/processing/src/sidecar-client.ts URL resolution, auth token handling, and fetch wrapper for all sidecar communication
apps/geolibre-desktop/vite.config.ts Vite configuration with SPA fallback denial for /sidecar routes
apps/geolibre-desktop/vite-proxy-guard.ts Development middleware for proxying binary and sidecar requests
backend/geolibre_server/pyproject.toml FastAPI sidecar package definition serving the actual endpoints

Summary

  • resolveSidecarBaseUrl() dynamically selects between http://127.0.0.1:8765 and ${origin}/sidecar based on environment detection.
  • sidecarFetch provides a unified request interface with optional token authentication for Tauri desktop builds.
  • Same-origin proxying via Vite middleware or nginx eliminates CORS handling in production deployments.
  • The design supports three deployment modes—development, Docker, and Tauri desktop—from a single codebase.

Frequently Asked Questions

How does GeoLibre avoid CORS issues between browser and sidecar?

GeoLibre uses same-origin reverse proxying. In production and Docker builds, the browser sends requests to /sidecar on its own origin, which nginx forwards to 127.0.0.1:8765. The browser sees the sidecar as same-origin, so no CORS preflight or headers are required.

What environment variable overrides the sidecar URL?

Set VITE_SIDECAR_URL to force a specific base URL. This bypasses all automatic detection and is useful when running the Vite dev server on non-standard ports or proxying through external infrastructure.

How does authentication work for the sidecar in desktop builds?

The Tauri shell generates a unique token at startup and configures nginx to inject it as the X-GeoLibre-Token header. The sidecarFetch function adds this header when sidecarAuthToken is populated. Browser builds omit the token entirely.

Why is navigateFallbackDenylist needed in vite.config.ts?

Without this denylist, the Vite PWA plugin's SPA router would intercept /sidecar/health and similar paths, returning the single-page application shell instead of proxying to the Python backend. The regex /^\/sidecar\// ensures these requests reach the actual sidecar API.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →