Skip to content

Session-authenticated examples

These examples use safe dummy identifiers and never embed a real checked-in credential. Set:

BASE_URL=https://geosync.example.invalid/geosync-service
SESSION_TOKEN=<raw Central acugis_session cookie from an authorized session>
PROJECT_ID=12

The Central cookie is opaque and must be protected like a password. Prefer a cookie jar with restrictive filesystem permissions. The examples first list projects (HTML), then read status HTML, start synchronization, and query the allowlisted analysis table endpoint. A 2xx action response is not enough: inspect success.

curl

curl --fail-with-body --cookie "acugis_session=$SESSION_TOKEN" \
  "$BASE_URL/admin/projects.php" -o projects.html

curl --fail-with-body --cookie "acugis_session=$SESSION_TOKEN" \
  "$BASE_URL/admin/project_settings.php?id=$PROJECT_ID&tab=synchronize" \
  -o status.html

curl --fail-with-body --cookie "acugis_session=$SESSION_TOKEN" \
  --data-urlencode "id=$PROJECT_ID" --data-urlencode "op=start" \
  "$BASE_URL/admin/action/backend.php"

curl --fail-with-body --get --cookie "acugis_session=$SESSION_TOKEN" \
  --data-urlencode "service=analysis" \
  --data-urlencode "path=api/tables" \
  --data-urlencode "connection_id=1" \
  --data-urlencode "schema=public" \
  "$BASE_URL/api/proxy.php"

JavaScript

In a browser on the GeoSync origin, use credentials: "include" and do not read or copy the HttpOnly cookie. Node callers can set the cookie explicitly:

const base = process.env.BASE_URL;
const token = process.env.SESSION_TOKEN;
const projectId = process.env.PROJECT_ID ?? "12";
const headers = { Cookie: `acugis_session=${token}` };

async function request(path, options = {}) {
  const response = await fetch(`${base}${path}`, {
    redirect: "manual",
    ...options,
    headers: { ...headers, ...options.headers },
  });
  if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  return response;
}

const projectsHtml = await (await request("/admin/projects.php")).text();
console.log(`projects page bytes: ${projectsHtml.length}`);

const body = new URLSearchParams({ id: projectId, op: "start" });
const action = await (await request("/admin/action/backend.php", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body,
})).json();
if (!action.success) throw new Error(action.message);

const query = new URLSearchParams({
  service: "analysis", path: "api/tables", connection_id: "1", schema: "public",
});
const tables = await (await request(`/api/proxy.php?${query}`)).json();
console.log(tables);

Python

import os
import requests

base = os.environ["BASE_URL"].rstrip("/")
project_id = os.getenv("PROJECT_ID", "12")
s = requests.Session()
s.cookies.set("acugis_session", os.environ["SESSION_TOKEN"])

r = s.get(f"{base}/admin/projects.php", timeout=30)
r.raise_for_status()
print("projects page bytes:", len(r.content))

r = s.post(
    f"{base}/admin/action/backend.php",
    data={"id": project_id, "op": "start"},
    timeout=30,
)
r.raise_for_status()
action = r.json()
if not action.get("success"):
    raise RuntimeError(action.get("message", "start failed"))

r = s.get(
    f"{base}/api/proxy.php",
    params={
        "service": "analysis",
        "path": "api/tables",
        "connection_id": 1,
        "schema": "public",
    },
    timeout=30,
)
r.raise_for_status()
print(r.json())

Go

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "strings"
)

type actionResult struct {
    Success bool   `json:"success"`
    Message string `json:"message"`
}

func main() {
    base := strings.TrimRight(os.Getenv("BASE_URL"), "/")
    token := os.Getenv("SESSION_TOKEN")
    projectID := os.Getenv("PROJECT_ID")
    if projectID == "" { projectID = "12" }

    do := func(req *http.Request) *http.Response {
        req.AddCookie(&http.Cookie{Name: "acugis_session", Value: token})
        resp, err := http.DefaultClient.Do(req)
        if err != nil { panic(err) }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            b, _ := io.ReadAll(resp.Body); resp.Body.Close()
            panic(fmt.Sprintf("HTTP %d: %s", resp.StatusCode, b))
        }
        return resp
    }

    req, _ := http.NewRequest(http.MethodGet, base+"/admin/projects.php", nil)
    resp := do(req); b, _ := io.ReadAll(resp.Body); resp.Body.Close()
    fmt.Println("projects page bytes:", len(b))

    form := url.Values{"id": {projectID}, "op": {"start"}}
    req, _ = http.NewRequest(http.MethodPost, base+"/admin/action/backend.php",
        strings.NewReader(form.Encode()))
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp = do(req)
    var result actionResult
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { panic(err) }
    resp.Body.Close()
    if !result.Success { panic(result.Message) }

    q := url.Values{
        "service": {"analysis"}, "path": {"api/tables"},
        "connection_id": {"1"}, "schema": {"public"},
    }
    req, _ = http.NewRequest(http.MethodGet, base+"/api/proxy.php?"+q.Encode(), nil)
    resp = do(req); defer resp.Body.Close()
    io.Copy(os.Stdout, resp.Body)
}

PHP

<?php
$base = rtrim(getenv('BASE_URL'), '/');
$token = getenv('SESSION_TOKEN');
$projectId = getenv('PROJECT_ID') ?: '12';

function call_geosync(string $url, string $token, ?array $form = null): array {
    $ch = curl_init($url);
    $options = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_HTTPHEADER => ['Cookie: acugis_session=' . $token],
        CURLOPT_TIMEOUT => 30,
    ];
    if ($form !== null) {
        $options[CURLOPT_POST] = true;
        $options[CURLOPT_POSTFIELDS] = http_build_query($form);
        $options[CURLOPT_HTTPHEADER][] =
            'Content-Type: application/x-www-form-urlencoded';
    }
    curl_setopt_array($ch, $options);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    $error = curl_error($ch);
    curl_close($ch);
    if ($body === false || $status < 200 || $status >= 300) {
        throw new RuntimeException("HTTP {$status}: {$error} {$body}");
    }
    return [$body, $status];
}

[$html] = call_geosync($base . '/admin/projects.php', $token);
echo 'projects page bytes: ' . strlen($html) . PHP_EOL;

[$body] = call_geosync(
    $base . '/admin/action/backend.php',
    $token,
    ['id' => $projectId, 'op' => 'start']
);
$action = json_decode($body, true, flags: JSON_THROW_ON_ERROR);
if (empty($action['success'])) {
    throw new RuntimeException($action['message'] ?? 'start failed');
}

$query = http_build_query([
    'service' => 'analysis',
    'path' => 'api/tables',
    'connection_id' => 1,
    'schema' => 'public',
]);
[$tables] = call_geosync($base . '/api/proxy.php?' . $query, $token);
echo $tables . PHP_EOL;

Downloading a retained version

First obtain the exact gpkg value from the authenticated Files settings HTML, then URL-encode it. Never concatenate an untrusted path:

curl --fail-with-body --cookie "acugis_session=$SESSION_TOKEN" \
  --get --data-urlencode "id=$PROJECT_ID" \
  --data-urlencode "gpkg=demo.1.gpkg" \
  "$BASE_URL/admin/action/files.php" -o demo.1.gpkg