WebAPI (server scripting)
Server-side scripts run as GSP (Groovy Server Pages) or .groovy endpoints. Scripts receive a number of globals — WebAPI among them — for working with HTTP and content (JCR).
Execution model
Scripts are stored as JCR content and invoked at:
/bin/cms.cgi/<workspace>/content/<path>/<script.groovy|.gsp>
Example: GET /bin/cms.cgi/web/content/commerce/endpoints/health.groovy?days=7
Script globals (main ones)
| Name | Type | Purpose |
|---|---|---|
out |
Writer |
write to the response body |
request / response |
HttpServletRequest / HttpServletResponse |
HTTP in/out |
session / application |
HttpSession / ServletContext |
session / app-shared state |
repositorySession |
Session (script resource API) |
the main way to read/write JCR content |
resource |
Resource |
the JCR resource being processed |
WebAPI |
WebAPI |
include / fetch / parameters / encoding (only when request exists) |
log (LoggerAPI) |
LoggerAPI |
logging (debug/info/warn/error) |
JSON / YAML |
— | JSON / YAML parse & serialize |
XPath / MetadataAPI |
— | query / metadata |
ProcessAPI / IntegrationAPI |
— | BPM / EIP integration |
EventAdminAPI / cluster / CryptoAPI / MimeTypeAPI / SessionAPI |
— | events / cluster / crypto / MIME / session creation |
(request / response / out are available only when the script is triggered over HTTP.)
WebAPI methods
| Method | Purpose |
|---|---|
include(path) |
include another resource (e.g. a GSP); a leading / is workspace-relative |
forward(path) |
forward to another resource |
importContent(path[, encoding]) |
write file / HTTP content (jcr://, relative/absolute path, or HTTP URL) |
getParameter(name) |
a request parameter (single value or an uploaded file) |
fetch(uri) |
HTTP GET (3s connect / 10s request timeout); returns a WebResource |
encodeURIComponent / encodeURI / decodeURIComponent |
URI encode/decode |
Session (script resource API)
Operate on content through repositorySession.
getResource(absPath)/getResourceByIdentifier(id)/getRootFolder()— get resourcescommit()/rollback()— save / discarddeploy()— applyetc/jcr/deployandetc/jcr/provisioningadaptTo(javax.jcr.Session)— adapt to the low-level JCR sessionimpersonate(userId)/newSession()— another user / a new sessionisAdmin()/isAnonymous()/isService()/getUserID()— who is running
Main Resource operations
- read:
getContent()/getContentAsStream()/getProperty(name)/list() - write:
write(content)/setProperty(name, value)/createFile()/createFolder()/getOrCreateFile(name) - move, etc.:
moveTo(path)/copyTo(path)/remove() - versioning:
addVersionControl()/checkout()/checkin()/checkpoint() - locking:
lock()/unlock()/isLocked() - ACL:
getAccessControlList()/setAccessControlList(acl)/canRead()/canWrite()
Examples
GSP include:
<% WebAPI.include("/content/public/inc/head_start.gsp") %>
A JSON endpoint (.groovy):
int days = (request.getParameter("days") ?: "7") as int
try {
def snapshot = Health.snapshot(repositorySession, days)
response.setStatus(200)
response.setHeader("Content-Type", "application/json")
response.getWriter().write(new ObjectMapper().writeValueAsString(snapshot))
} catch (Exception e) {
log.error("health endpoint error: ${e.message}", e)
response.setStatus(500)
}
Create and save content:
def res = repositorySession.getRootFolder().getOrCreateFile("content/notes/hello.json")
res.write('{"hello":"world"}')
res.setProperty("jcr:mimeType", "application/json")
repositorySession.commit()
For authorization and service accounts, see "Users, roles & permissions".
Folder descriptor .web.yml (publishing & rendering)
Dropping a .web.yml into a folder declares how the files in that folder (and its descendants) behave when served. It is a configuration file and is never delivered over the web. Settings are resolved by walking up to the nearest ancestor folder's .web.yml.
Site document root (site.root)
site:
root: true # make this folder the public site root (URL `/`)
baseURL: "https://example.com" # canonical public origin (optional metadata)
The folder that declares root: true becomes the document root. Placed at /content/public, for example, the public site mounts that folder at / (e.g. NGINX maps /index.gsp → /content/public/index.gsp).
This makes site-root-absolute paths inside the content (e.g. href="/docs/css/docs.css", src="/img/logo.svg") resolve correctly for whichever mount point serves them. Authors keep writing absolute paths, and the same content looks identical through either path:
| Serving path | Where /docs/css/docs.css resolves |
|---|---|
| Public site | At the origin root (https://example.com/docs/css/docs.css) |
| webtop text-editor preview | /bin/cms.cgi/<workspace>/content/public/docs/css/docs.css |
The preview performs this rewrite with a Service Worker, so it requires HTTPS (a secure context). Over HTTP — or for files in a folder that does not declare a root — absolute paths are not rewritten (relative paths still resolve as before).
baseURLis optional metadata describing the canonical origin; the path-based preview rewrite does not need it.
Binding to a template (render)
Source files (e.g. *.md) can be bound to a template per folder, instead of configuring each file, and rendered through it.
render:
- match: "*.md" # glob (supports * ?) matched against the file name
template: "/content/WEB-INF/templates/doc.html"
output: ["html"] # allowed output extensions (any when omitted)
An explicit web.template property set on a file takes precedence. The resolved binding and document root are exposed via GraphQL as node.webRender (templated / fromDescriptor / source / outputs / documentRoot).