boxlang-web-development — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited boxlang-web-development (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.
BoxLang web applications revolve around Application.bx, which acts as the application lifecycle controller. The runtime handles HTTP requests through a well-defined lifecycle, with full support for REST, sessions, CSRF, SSE, and both MiniServer (dev) and CommandBox (production) deployment.
For a deep dive into multi-app isolation, descriptor discovery, and advanced Application.bx patterns, see the application-descriptor skill.
Application.bx lives at the web root and configures the entire application:
// Application.bx
class {
// Application settings
this.name = "MyApp"
this.sessionManagement = true
this.sessionTimeout = createTimeSpan( 0, 2, 0, 0 ) // 2 hours
this.applicationTimeout = createTimeSpan( 1, 0, 0, 0 ) // 1 day
this.setClientCookies = true
// Java classpath additions
this.javaSettings = {
loadPaths: [ "lib/" ],
loadColdFusionClassPath: false,
reloadOnChange: false
}
// Datasource defaults
this.datasource = "mainDB"
// --- Lifecycle Events ---
// Fires once when the application first starts
boolean function onApplicationStart() {
application.version = "1.0.0"
application.config = loadConfig()
return true
}
// Fires before every request
boolean function onRequestStart( required string targetPage ) {
// Auth checks, request logging, CORS headers
if ( !isAuthenticated() && !isPublicRoute( arguments.targetPage ) ) {
location( url="/login", addToken=false )
}
return true
}
// Fires after every request
void function onRequestEnd( required string targetPage ) {
// Cleanup, audit logging
}
// Called when request target is a .bx file (optional — allows custom routing)
void function onRequest( required string targetPage ) {
include arguments.targetPage
}
// Fires when a new session starts
boolean function onSessionStart() {
session.cart = []
session.userId = ""
session.isLoggedIn = false
return true
}
// Fires when a session ends
void function onSessionEnd( required struct sessionScope, required struct appScope ) {
auditService.recordLogout( arguments.sessionScope.userId )
}
// Global error handler
boolean function onError( required any exception, required string eventName ) {
errorService.log( arguments.exception )
include "views/error.bxm"
return true
}
// Missing template handler
boolean function onMissingTemplate( required string targetPage ) {
location( url="/404" )
return true
}
}// URL variables (?key=value)
var page = url.page ?: 1
var query = url.q ?: ""
// Form variables (POST body)
var username = form.username ?: ""
var password = form.password ?: ""
// CGI scope
var userAgent = cgi.http_user_agent
var requestMethod = cgi.request_method // GET, POST, PUT, DELETE
var remoteAddr = cgi.remote_addr
var serverName = cgi.server_name
// Request scope (per-request shared storage)
request.startTime = getTickCount()
request.userId = session.userId// Process a form submission
if ( cgi.request_method == "POST" ) {
// Validate
if ( !len( trim( form.email ) ) ) {
request.errors.append( "Email is required" )
}
if ( !request.errors.len() ) {
userService.create({
email : form.email,
username : form.username,
password : hashPassword( form.password )
})
location( url="/dashboard", addToken=false )
}
}// REST endpoint using onRequest routing in Application.bx
void function onRequest( required string targetPage ) {
var method = cgi.request_method
var path = cgi.path_info
var router = new Router()
router.get( "/api/users", "handlers.UsersHandler", "index" )
router.post( "/api/users", "handlers.UsersHandler", "create" )
router.get( "/api/users/:id", "handlers.UsersHandler", "show" )
router.put( "/api/users/:id", "handlers.UsersHandler", "update" )
router.delete( "/api/users/:id", "handlers.UsersHandler", "delete" )
router.dispatch( method, path )
}
// Handler: handlers/UsersHandler.bx
class {
function index() {
var users = userService.findAll()
renderJSON( users )
}
function show( required numeric id ) {
var user = userService.findById( arguments.id )
if ( isNull( user ) ) {
httpStatus( 404 )
renderJSON({ error: "Not found" })
return
}
renderJSON( user )
}
function create() {
var data = jsonDeserialize( getHTTPRequestData().content )
var user = userService.create( data )
httpStatus( 201 )
renderJSON( user )
}
}
// Helper functions
function renderJSON( required any data ) {
bx:header name="Content-Type" value="application/json";
writeOutput( jsonSerialize( arguments.data ) )
abort
}
function httpStatus( required numeric code ) {
bx:header statusCode=arguments.code;
}// Simple GET
var response = httpGet( "https://api.example.com/data" )
var data = jsonDeserialize( response.fileContent )
// Full bx:http request
bx:http url="https://api.example.com/users" method="POST" result="apiResponse" {
bx:httpparam type="header" name="Authorization" value="Bearer #token#"
bx:httpparam type="header" name="Content-Type" value="application/json"
bx:httpparam type="body" value=jsonSerialize({ name: "Ada", email: "[email protected]" })
}
var response = jsonDeserialize( apiResponse.fileContent )
// HTTP with query string
bx:http url="https://api.example.com/search" method="GET" result="searcharesult" {
bx:httpparam type="url" name="q" value="boxlang"
bx:httpparam type="url" name="limit" value="10"
}
// File download
bx:http url="https://example.com/report.pdf" method="GET" result="pdfResponse"
getAsBinary="yes"
fileWrite( expandPath( "./downloads/report.pdf" ), pdfResponse.fileContent )// Set session values
session.userId = user.getId()
session.username = user.getUsername()
session.isLoggedIn = true
session.cart = []
// Check session
if ( session.isLoggedIn ?: false ) {
// Authenticated
}
// Invalidate session on logout
sessionInvalidate()
location( url="/login", addToken=false )
// Extend session programmatically
sessionRotate()// Generate CSRF token (stores in session)
var token = csrfGenerateToken( "loginForm" )
// In your form (bxm template):
// <input type="hidden" name="csrfToken" value="#csrfGenerateToken('loginForm')#">
// Validate on POST
if ( !csrfVerifyToken( form.csrfToken, "loginForm" ) ) {
httpStatus( 403 )
writeOutput( "Invalid CSRF token" )
abort
}// SSE endpoint: sse/updates.bxs
bx:header name="Content-Type" value="text/event-stream";
bx:header name="Cache-Control" value="no-cache";
bx:header name="X-Accel-Buffering" value="no";
var i = 0
while ( i < 100 ) {
var data = getLatestUpdates()
writeOutput( "data: #jsonSerialize(data)##char(10)##char(10)#" )
flush
sleep( 1000 )
i++
}// Include a template
include "views/header.bxm"
include "views/user/profile.bxm"
// Save output to variable
var rendered = ""
savecontent variable="rendered" {
include "views/email/welcome.bxm"
}
// Set response headers
cfheader( name="X-Custom-Header", value="myValue" )
cfcontent( type="application/pdf" )
// Redirect
location( url="/dashboard", addToken=false )
location( url="/login", statusCode=302 )miniserver.json in the project root:
{
"host": "localhost",
"port": 8080,
"webroot": "./www",
"debug": true,
"warmUpURLs": ["/"],
"rewrites": {
"enable": true,
"config": "urlrewrite.xml"
}
}Start MiniServer:
boxlang-miniserver
# or via CommandBox
box server startserver.json:
{
"name": "MyApp",
"web": {
"http": { "port": 8080 },
"https": { "port": 8443, "enable": true },
"webroot": "www"
},
"app": {
"cfengine": "boxlang",
"javaVersion": "openjdk21_jdk"
},
"jvm": {
"heapSize": "512m",
"maxHeapSize": "1024m",
"args": "-Duser.timezone=UTC"
},
"env": {
"DB_HOST": "localhost",
"DB_NAME": "myapp"
}
}BoxLang 1.8.0+ provides the soap() BIF for consuming SOAP 1.1/1.2 web services. It automatically parses WSDL documents and converts SOAP XML responses to BoxLang native types.
// Create client from WSDL URL
var ws = soap( "http://example.com/service.wsdl" )
// Invoke an operation with named parameters
var result = ws.invoke( "getCustomer", { customerId: 12345 } )
writeOutput( "Name: #result.customerName#" )var ws = soap( "http://example.com/service.wsdl" )
.withBasicAuth( "apiUser", "secret" )
.timeout( 30 )
var customer = ws.invoke( "getCustomer", { customerId: 42 } )var ws = soap( "http://secure.example.com/service.wsdl" )
.header( "X-API-Key", "abc123" )
.header( "X-Tenant-ID", "tenant001" )
.timeout( 45 )
var result = ws.invoke( "getData" )var ws = soap( "http://example.com/service.wsdl" )
// List all available operations
var operations = ws.getOperations()
operations.each( ( op ) -> writeOutput( op & "<br>" ) )
// Get input parameter details for an operation
var info = ws.getOperationInfo( "createOrder" )
info.inputParameters.each( ( param ) -> {
writeOutput( "#param.name# (#param.type#)<br>" )
})try {
var ws = soap( "http://example.com/service.wsdl" )
var result = ws.invoke( "processOrder", { orderId: orderId } )
} catch ( "soap.Fault" e ) {
writeOutput( "SOAP fault: #e.message#" )
} catch ( "soap.ConnectionError" e ) {
writeOutput( "Connection failed: #e.message#" )
} catch ( any e ) {
writeOutput( "Unexpected error: #e.message#" )
}When to use `soap()` vs `bx:http`:
Use soap() | Use bx:http / httpGet() |
|---|---|
| Enterprise/legacy SOAP services | Modern REST/JSON APIs |
| WSDL-defined contracts | Lightweight, fast communication |
| WS-Security required | JSON preferred |
| Complex type mapping | Simple HTTP calls |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.