Skip to content

Cesivi URL Contract

Created: 2026-04-14 (PLAN-1020 Phase 4)

This document defines the URL routing contract for Cesivi. All SharePoint protocol endpoints are served same-origin through the WebUI host on port 443. Internal server ports are never exposed to browsers.


Topology

Browser ──── HTTPS 443 ────→ Cesivi.WebUI (IIS / Kestrel)
                                    │
                          ┌─────────┴──────────────────────────┐
                          │         YARP / Custom Proxy         │
                          │   /signalr/*  ─────────────────┐   │
                          │   /_api/*     ─────────────────┤   │
                          │   /_vti_bin/* ─────────────────┤   │
                          │   /_catalogs/*─────────────────┤   │
                          │   /_trust/*   ─────────────────┤   │
                          └────────────────────────────────┼───┘
                                                           │
                               HTTP loopback ──────────────▼
                                         Cesivi.Server (:5010 internal)

Key rule: Browsers ONLY ever send requests to the WebUI host. The internal server port (default 5010) is never exposed to the public network.


YARP + Custom Proxy Route Table

Path Prefix Handler Notes
/signalr/* SignalRProxyMiddleware (YARP IHttpForwarder) WebSocket + HTTP negotiate
/_api/* CesiviApiProxyMiddleware (HTTP) REST API — top-level
/_vti_bin/* CesiviApiProxyMiddleware (HTTP) SOAP + CSOM
/_vti_pvt/* CesiviApiProxyMiddleware (HTTP) FPSE web services
/_spmock/* CesiviApiProxyMiddleware (HTTP) Cesivi internal API
/_trust/* CesiviApiProxyMiddleware (HTTP) SAML/WS-Federation redirect target
/_catalogs/* CesiviApiProxyMiddleware (HTTP) Master pages, web templates, solution gallery
/health, /ready, /live CesiviApiProxyMiddleware (HTTP) Health check endpoints
{subweb}/_api/* CesiviApiProxyMiddleware (deep path) Sub-web REST — marker /_api/ found anywhere
{subweb}/_vti_bin/* CesiviApiProxyMiddleware (deep path) Sub-web SOAP/CSOM
/_layouts/* Cesivi.WebUI Razor Pages NOT proxied — served by WebUI directly
/css/*, /js/*, /lib/* UseStaticFiles Static assets
/api/Search/* Cesivi.WebUI SearchController WebUI's own search controller
Everything else Cesivi.WebUI Razor Pages Default — UI pages

URL Samples by Object Type

REST API

Object URL
Web properties https://cesivi.devlab.farm/_api/web
List by title https://cesivi.devlab.farm/_api/web/lists/getbytitle('Tasks')
List items https://cesivi.devlab.farm/_api/web/lists/getbytitle('Tasks')/items
File content https://cesivi.devlab.farm/_api/web/getfilebyserverrelativeurl('/Documents/file.docx')/$value
Sub-web list https://cesivi.devlab.farm/subweb/_api/web/lists/getbytitle('Notes')
Host-named site https://cesivi.devlab.farm/sites/team/_api/web

CSOM

Object URL
CSOM batch endpoint https://cesivi.devlab.farm/_vti_bin/client.svc/ProcessQuery
Sub-web CSOM https://cesivi.devlab.farm/subweb/_vti_bin/client.svc/ProcessQuery

SOAP

Service URL
Lists.asmx https://cesivi.devlab.farm/_vti_bin/Lists.asmx
Webs.asmx https://cesivi.devlab.farm/_vti_bin/Webs.asmx
Authentication.asmx https://cesivi.devlab.farm/_vti_bin/Authentication.asmx

SignalR

Object URL
SignalR hub https://cesivi.devlab.farm/signalr/changes
Negotiate endpoint POST https://cesivi.devlab.farm/signalr/changes/negotiate

Web UI Pages

Page URL
Home https://cesivi.devlab.farm/
List view https://cesivi.devlab.farm/Lists/Tasks/AllItems.aspx
New item form https://cesivi.devlab.farm/Lists/Tasks/NewForm.aspx
Edit item https://cesivi.devlab.farm/Lists/Tasks/EditForm.aspx?ID=1
Server diagnostics https://cesivi.devlab.farm/_layouts/15/ServerDiag.aspx
Central Admin https://cesivi.devlab.farm/_admin/

Multiple Web Applications (HNSC)

Host-named site collections use the same origin with different path prefixes:

Site URL
Root https://cesivi.devlab.farm/
Sub-site https://cesivi.devlab.farm/subweb/
Named site collection https://cesivi.devlab.farm/sites/team/
App web (Addin) https://cesivi.devlab.farm/appwebs/{id}/

Do / Don't Rules for Authors

DO

  • ✅ Use relative URLs in all client-side JavaScript: fetch('/_api/web', ...)
  • ✅ Use Request.Scheme + "://" + Request.Host in server-side code when you need a full URL (e.g., SAML redirects)
  • ✅ Use the WebUI origin as the SignalR server URL (CesiviRealTime.init(serverUrl, ...) where serverUrl is the WebUI host)
  • ✅ Register new proxy paths in CesiviApiProxyMiddleware.ProxiedPrefixes when Cesivi.Server adds new top-level endpoints

DON'T

  • ❌ Never hardcode http://localhost:5010 or http://127.0.0.1:5010 in any client-visible file
  • ❌ Never embed _restClient.BaseUrl in responses rendered to the browser
  • ❌ Never use absolute Cesivi.Server URLs in JavaScript files (wwwroot/**/*.js)
  • ❌ Never use absolute Cesivi.Server URLs in Razor pages (.cshtml or .cshtml.cs) that are rendered to the browser
  • ❌ Never configure ApiBaseUrl or similar to point at the internal server port

Middleware Pipeline Order (Critical)

The order matters. Incorrect ordering breaks WebSocket upgrades or static file serving.

1. UseHttpsRedirection
2. UseResponseBuffering
3. UseStaticFiles          ← serves /js/, /css/, /lib/signalr/signalr.min.js
4. UseWebSockets           ← enables WebSocket upgrade protocol in Kestrel
5. UseSignalRProxy         ← YARP proxy: /signalr/* → Server:5010
6. UseCesiviApiProxy       ← HTTP proxy: /_api/*, /_vti_bin/*, /_catalogs/*, /_trust/*
7. UseWebContext           ← extracts sub-web path prefix
8. UseWikiPages            ← URL rewriting for wiki pages
9. UseFormsPattern         ← URL rewriting for /Lists/.../Form.aspx patterns
10. UseViewUrls             ← URL rewriting for view URLs
11. UseRouting
12. UseAuthentication
13. UseIisWindowsAutoSignIn
14. UseAuthorization
15. MapRazorPages / MapControllers

Testing

Same-origin contract regression tests live in Cesivi.Tests.WebUI/BrowserTests/SameOriginContractTests.cs:

Test Validates
SameOrigin_HomePage_NoInternalHostsLeak Rendered HTML contains no 127.0.0.1, :5010, mocksharepoint.local
SameOrigin_AllItems_NoInternalHostsLeak AllItems page has no internal host leak
SameOrigin_SignalRScript_UsesWebUIOrigin SignalR init gets the WebUI origin, not the internal server URL
SameOrigin_RestApi_ViaWebUI_Returns200 GET /_api/web through WebUI port succeeds
SameOrigin_CSOM_ViaWebUI_Returns200 POST /_vti_bin/client.svc/ProcessQuery through WebUI port succeeds

Last updated: 2026-04-14 (PLAN-1020 Phase 4)