NOTICE: All information contained herein is, and remains
the property of TechnoCore Automate.
FastAPI endpoint module for the Go URL shortener service.
Provides redirect routes, REST API, analytics dashboard,
status page, API docs, bulk import form, and static assets.
WebPageGo.py registers all HTTP routes on
WebServer.app. It delegates business logic to
ObjGo.ObjGo and renders report dashboards via
ObjReportGoAnalytics and ObjReportGoStatus.
Run via ServeGo.py (default port 9100).
Apache balancer proxy for production:
<Proxy "balancer://go/">
BalancerMember "http://localhost:9400/go"
route=route2 loadfactor=1
</Proxy>
<Proxy "balancer://qr/">
BalancerMember "http://localhost:9400/qr"
route=route2 loadfactor=1
</Proxy>
ProxyPass /go/ "balancer://go/"
ProxyPassReverse /go/ "balancer://go/"
ProxyPass /g/ "balancer://go/"
ProxyPassReverse /g/ "balancer://go/"
ProxyPass /map/ "balancer://go/"
ProxyPassReverse /map/ "balancer://go/"
ProxyPass /qr/ "balancer://qr/"
ProxyPassReverse /qr/ "balancer://qr/"
| Method | Route | Description |
|---|---|---|
| GET | /go/{code} |
Redirect (303). Rate-limited, UTM passthrough. |
| GET | /g/{code} |
Alias for /go/{code} |
| GET | /~/{code} |
Alias for /go/{code} |
| GET | /map/{code} |
Alias for /go/{code} |
| POST | /go/{code} |
Password submission for protected links |
| GET | /go/{code}?preview=1 |
Preview page with QR, stats, A/B info |
| Method | Route | Auth | Description |
|---|---|---|---|
| POST | /api/go/create |
x-api-key | Create a mapping (JSON body) |
| PUT | /api/go/{code} |
x-api-key | Update target URL |
| DELETE | /api/go/{code} |
x-api-key | Delete a mapping |
| GET | /api/go/list |
x-api-key | List mappings (paginated: limit, offset, go_set) |
| GET | /api/go/{code}/stats |
x-api-key | Link stats with geo and A/B breakdown |
| GET | /api/go/search?q={term} |
x-api-key | Search by code, URL, or GoSet |
| GET | /api/go/health |
-- | Health check with uptime, counts, system metrics |
Access control (P1+P2): the read routes above and the dashboards
(/go/dashboard,/go/status) require authorization — they were anonymous, a
cross-tenant exposure. A read is allowed for either a machine client with
a validx-api-keyor a logged-in user whose session carries the
go_readACL grant (validate_report, grant/epoch-aware). Redirects
(/go/{code}+ aliases) stay public. Tenant scoping resolves
ObjGo.active_package()(env-active package), notget_package()(the
cached config default, which leaked on sister-site hosts). Mutations
(create/update/delete+ the legacyPOST /go/, which was previously
unauthenticated) are gated by_authorize_write: anx-api-key(machine,
scoped to the key's package) or a session with thego_admingrant + a
CSRF token (scoped to the active package)./go/importkeeps its form-field
api-key. Thego_read/go_admingrants aredef_reportrows seeded per
package (factory.deploy/ObjSeed.py grants). See
resource.notes/security/objgo_access_control_plan.md.
| Method | Route | Description |
|---|---|---|
| POST | /go/ |
Create mapping (JSON: source, target, hitsexpires, timeexpires) |
| Method | Route | Description |
|---|---|---|
| GET | / |
Landing page with white-label branding and dark-mode toggle |
| GET | /go/dashboard |
Analytics dashboard (HTML). ?format=json for JSON. |
| GET | /go/status |
Service status dashboard (HTML). ?format=json for JSON. |
| GET | /go/docs |
API reference page |
| GET | /go/import |
Bulk CSV import form |
| POST | /go/import |
Process bulk import (requires API key in form) |
| Method | Route | Description |
|---|---|---|
| GET | /favicon.ico |
Favicon from resource.web/local/ |
| GET | /logo.png |
Brand logo PNG |
| GET | /logo-dark.png |
Dark-mode brand logo PNG |
| GET | /qr/{code} |
Branded QR code PNG for a short code |
Configured via go.rate_limit_rpm in config.yaml
(default 60). Per-IP sliding window of 60 seconds. When
exceeded, returns HTTP 429 "Rate limit exceeded".
Implemented in _check_rate_limit() using an in-memory
dict _RATE_LIMITS.
Mutating endpoints (create, edit, delete) require an
x-api-key header. Keys are configured in config.yaml
under go.api_keys as a dict mapping package names to
key strings.
Implemented in _validate_api_key(). Returns
(valid, package_name).
When redirect requests include UTM query parameters
(utm_source, utm_medium, utm_campaign,
utm_content, utm_term), they are extracted by
_extract_utm() and passed to ObjGo.find_map(),
which appends them to the target URL.
The landing page reads branding from config.yaml
via _get_brand():
go.brand_name -- page title and headergo.brand_tagline -- hero section taglinego.brand_description -- meta descriptiongo.brand_footer -- footer attributionThe landing page includes a dark-mode toggle button and
respects prefers-color-scheme: dark. User preference is
persisted in localStorage as go_dark.
go_landing_page() -> HTMLResponseRenders the branded landing page. Called for GET /.
_check_rate_limit(ip_address) -> boolReturns True if the IP is within rate limits.
_validate_api_key(request) -> tuple[bool, str]Validates the x-api-key header. Returns (valid, pkg).
_extract_utm(request) -> dict[str, str]Extracts UTM query params from request.
_get_client_ip(request) -> strDelegates to WebServer.get_client_ip().
_get_brand(key, default) -> strReads a go.brand_* value from config.yaml.
_render_preview(short_code) -> HTMLResponseRenders the preview page for a short link.
_render_expiry_page(short_code) -> strRenders the branded expiry page (HTTP 410).
_password_form(short_code, error) -> strRenders the password input form for protected links.
_import_result_page(results, error) -> strRenders the bulk import results page.
cythonize -3 -a -i WebPageGo.py
Compiling factory.pages/WebPageGo.py
Updated: 2026-05-02