Quick Start

Get started with WebPascal 5 in 10 minutes.

Step 1: Download & Extract

Download the package from the official website and extract it to any directory.

Step 2: Configure

Edit SrvConfig.ini to set the port (default 8833), CORS, GZip, etc.

Step 3: Start Service

Double‑click webpascal.exe; the console will show HTTP Server running on :8833, press Enter to stop... when successful.

Step 4: First Script

Create script/hello.api with:

// Hello World example
writeln('Hello WebPascal 5!');
writeln('The ultimate web development tool for Delphi developers!');

Access http://localhost:8833/ask/hello.api to see the output.

Directory Structure

WebPascal/
├── script/      # Web scripts (supports multi‑level subdirectories)
├── task/        # Scheduled task scripts (no subdirectories)
├── uploads/     # Uploaded files (auto‑organized by date)
├── www/         # Static resources (HTML/CSS/JS/images)
├── log/         # Logs (auto‑generated by date, 30‑day retention)
└── cache/       # Temporary files (auto‑cleaned)
                    

Installation & Deployment

System Requirements

  • Windows 7+ / Windows Server 2012+ (32/64-bit)
  • CPU ≥1 core, RAM ≥1GB, disk ≥100MB
  • No Delphi IDE required

Configuration

Core settings in SrvConfig.ini:

Port=8833          # Running port
CORS=1             # Enable CORS (1) or disable (0)
GZip=1             # Enable GZip compression (1) or disable (0)
UpDir=.\Uploads    # File upload path
                    

Run as a Windows Service

You can register webpascal.exe as a Windows service using nssm.

Basic Syntax

Fully compatible with Delphi native syntax:

  • Variable declaration: var i: Integer; s: string;
  • Loops: for, while, repeat‑until
  • Conditions: if‑else, case
  • Common functions: writeln, FormatDateTime, IntToStr, Trim
  • Comments: //, { }, (* *)

Modularization: include('common.api');

JSON Handling

// 1. Parse JSON string
var jsonStr := '{"name":"张三","age":18,"gender":"男"}';
var obj := json.parse(jsonStr);

// 2. Get JSON values (supports default operator ?? to avoid null errors)
var name := obj.name; // direct access, returns null if key does not exist
var email := obj.email ?? '未设置'; // returns default if key does not exist

// 3. Modify JSON object
obj.age := int(20);

// 4. Convert JSON object to string
var newJsonStr := json.stringify(obj);
writeln(newJsonStr);
writeln(unicodetoansi(newJsonStr));

// 5. Iterate over JSON object
for var i := 0 to obj.length() - 1 do
begin
    writeln(obj.ElementName(i) + ' : ' + obj[i] + ' | ' + obj[i].TypeName());
end;

Encoding Conversions

// 1. URL encode (supports emoji)
var urlStr := 'https://webpascal.com?name=张三😊';
var urlEnStr := urlencode.encode(urlStr);
writeln('URL encoded: ' + urlEnStr);

// 2. URL decode
var urlDeStr := urlencode.decode(urlEnStr);
writeln('URL decoded: ' + urlDeStr);

// 3. Base64 encode
var base64EnStr := base64.encode('WebPascal 5');
writeln('Base64 encoded: ' + base64EnStr);

// 4. Base64 decode
var base64DeStr := base64.decode(base64EnStr);
writeln('Base64 decoded: ' + base64DeStr);

// 5. HEX encode
var hexEnStr := StrToHex('abc测试123');
writeln('HEX encoded: ' + hexEnStr);

// 6. HEX decode
var hexDeStr := HexToStr(hexEnStr);
writeln('HEX decoded: ' + hexDeStr);

Regular Expressions

// 1. Match pattern (e.g., phone number validation)
var phone := '13800138000';
var isPhone := regex.ismatch(phone, '^1[3-9]\\d{9}$');
if isPhone then
    writeln('手机号格式正确')
else
    writeln('手机号格式错误');

// 2. Extract match (e.g., domain from URL)
var url := 'https://webpascal.com/docs';
var domain := regex.match(url, '(?<=https://).*?(?=/)');
writeln('提取的域名:' + domain);

// 3. Replace (replace all digits with *)
var str := 'abc123def456';
var newStr := regex.replace(str, '\\d+', '*');
writeln('替换后:' + newStr);

Database Operations

Connection Configuration

// SQLite
db.conn('mydb', 'DriverID=SQLite;Database=.\sqlite.db');

// MySQL
db.conn('mydb', 'DriverID=MySQL;Server=127.0.0.1;Database=test;User_name=root;Password=123456');

// SQL Server (trusted connection)
db.conn('mydb', 'DriverID=MSSQL;Server=.;Database=test;OSAuthent=Yes');
Supported databases and corresponding connection strings, see FireDAC Database Connectivity Documentation.

Query

include('/conn.cfg');

var res := json.parse(db.query('mydb', 'SELECT * FROM tEmployee WHERE FID=:p1 and FClose=:p2', 3, 0));

if res.code = 200 then // 200 indicates success
begin
    writeln('查询到 ' + IntToStr(res.data.length()) + ' 条数据');
    // Iterate result set
    for var i := 0 to res.data.length() - 1 do
    begin
        var user := res.data[i];
        writeln('用户名:' + user.FID + '|' + user.FName + ',级别:' + IntToStr(user.FLevel));
    end;
end
else
begin
    writeln('查询失败:' + res.msg);
end;

Insert/Update/Delete

// Insert
var addRes := json.parse(db.exec('mydb', 'INSERT INTO tEmployee(FName, FLevel) VALUES(:p1, :p2)', '李四', 1));
if addRes.code = 200 then
    writeln('新增成功,影响行数:' + IntToStr(addRes.rowcount))
else
    writeln('新增失败:' + addRes.msg);

// Update
var updateRes := db.exec('mydb', 'UPDATE tEmployee SET FLevel=:p2 WHERE FID=:p1', 3, 2);

// Delete
var deleteRes := db.exec('mydb', 'DELETE FROM tEmployee WHERE FID=:p1', 4);
You must use parameter placeholders :p1 ~ :p18 to prevent SQL injection.

HTTP Client

WebPascal 5 has a built‑in HTTP client that supports common request methods, as shown below:

GET Request

var getResult := http.get('https://api.example.com/users?id=123', '', '');
writeln(getResult);

POST Form

var postResult := http.post('https://api.example.com/users', '', 'name=张三&age=18');
writeln(postResult);

POST JSON

var jsonData := '{"name":"张三","age":18}';
var jsonResult := http.json('https://api.example.com/users', '', jsonData);
writeln(jsonResult);

PUT Request

var putResult := http.put('https://api.example.com/users/123', '', 'name=李四');
writeln(putResult);

DELETE Request

var deleteResult := http.delete('https://api.example.com/users/123', '', '');
writeln(deleteResult);

Form Upload (with file)

var uploadResult := http.formdata(
    'https://api.example.com/upload', 
    'Authorization: Bearer token', 
    'filename=file(/local/image.jpg)'
);
writeln(uploadResult);

File Transfer (save to server)

var savedPath := http.getfile('https://example.com/image.jpg');
writeln('<img src="' + savedPath + '">');

Note: http.getfile saves the remote file to the server's uploads directory and returns a /up/... path.

Request with Encoding and Timeout

var result := http.get(
    'https://api.example.com', 
    '', 
    '', 
    'utf8',    // request encoding
    'utf8',    // response encoding
    5000       // timeout in milliseconds
);

Note: The encoding parameter uses 'utf8' (without hyphen).

Scheduled Tasks

Create a script in the task directory and add a <task> configuration block at the top.

Schedule Modes:

  • Mode 0: Cycle by seconds; time is the number of seconds, e.g., "10" means execute every 10 seconds.
  • Mode 1: Fixed date/time; format yyyyMMddHHmmss, e.g., "20180520000000" means execute at 2018-05-20 00:00:00.
  • Mode 2: Yearly; format MMddHHmmss, e.g., "0520000000" means execute every year on May 20 at 00:00:00.
  • Mode 3: Monthly; format ddHHmmss, e.g., "20000000" means execute on the 20th of each month at 00:00:00.
  • Mode 4: Daily; format HHmmss, e.g., "000000" means execute every day at 00:00:00.

Example (per‑second execution):

<task>
{
    "title": "按秒执行任务",
    "mode": 0,
    "time": "10"
}
</task>
logger.info('任务执行中...');

Other mode examples:

// Fixed date/time (2018-05-20 00:00:00)
{"title": "按年月日执行任务","mode": 1,"time": "20180520000000"}

// Yearly (May 20 00:00:00 every year)
{"title": "按月日执行任务","mode": 2,"time": "0520000000"}

// Monthly (20th of each month at 00:00:00)
{"title": "按日执行任务","mode": 3,"time": "20000000"}

// Daily (every day at 00:00:00)
{"title": "按时间执行任务","mode": 4,"time": "000000"}

Debugging: Remove the <task> block and move the script to the script directory to test via URL; after debugging, move it back to task and restore the block.

Built-in Tools

  • Captcha: captcha('1234', 80) returns image data URL
  • QR Code: QRCode('https://webpascal.com', 80, 2)
  • Time handling: Now, FormatDateTime, UnixTime, LocalDateTimeToUnixTime, UnixTimeToLocalDateTime
  • Snowflake ID: Snowflake(1,2) generates a unique ID
  • Capacity formatting: ByteSizeToStr(1024^3) → 1GiB; FormatCapacity(1024^3) → 1.07GB

Global Variables

WebPascal 5 provides a global variable management feature to share data between scripts. All global variables are stored in server memory and are cleared when the service restarts.

Writing Global Variables

WriteGlobalVar('user_name', '张三');
WriteGlobalVar('login_time', Now);
WriteGlobalVar('visit_count', 100);
WriteGlobalVar('user_data', '{"id":123,"role":"admin"}'); // store JSON string

Reading Global Variables

var name := ReadGlobalVar('user_name');
var time := ReadGlobalVar('login_time');

Reading with Default Value

var count := ReadGlobalVarDef('visit_count', 0);

Reading and Parsing JSON

var userData := json.parse(ReadGlobalVarDef('user_data', '{}'));

Deleting a Global Variable

DeleteGlobalVar('user_name');

Listing Variables

// Get all variable names (supports * wildcard)
var allVars := GlobalVarsNames('*').Sort.Join(',');
var userVars := GlobalVarsNames('user_*').Sort.Join(',');

Clearing All Global Variables

CleanupGlobalVars;
Global variables are lost when the service restarts. They are suitable for temporary data storage, session management, caching, etc.

Security & Encryption

JWT Authentication

var token := jwt.encode('mySecretKey', '{"userId":1,"userName":"张三"}', 7);
writeln('生成的令牌:' + token);

if jwt.verify('mySecretKey', token) then
begin
    writeln('令牌验证成功');
    var jwtData := json.parse(base64.decode(regex.match(token, '(?<=\\.).*?(?=\\.)')));
    writeln('<br>' + jwtData);
    writeln('<br>创建: ' + formatdatetime('yyyy-MM-dd hh:nn:ss.zzz', UnixTimeToLocalDateTime(jwtData.iat)));
    writeln('<br>过期: ' + formatdatetime('yyyy-MM-dd hh:nn:ss.zzz', UnixTimeToLocalDateTime(jwtData.exp)));
    if UnixTime > jwtData.exp then
    begin
        writeln('<br><font color=red>已超时!</font>');
        exit;
    end;
end
else
    writeln('令牌验证失败!');

Hash Algorithms

// MD5
var md5Str := hash.hash('123456', hMD5);
writeln('MD5加密:' + md5Str);

// SHA256
var sha256Str := hash.hash('123456', hSHA256);
writeln('SHA256加密:' + sha256Str);

// SM3 (Chinese national standard)
var sm3Str := hash.hash('123456', hSM3);
writeln('SM3加密:' + sm3Str);

Supported hash algorithms: sm3, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512, sha1, md5. Parameters must be prefixed with h, e.g., hSHA256.

Symmetric Encryption

// AES encryption
var key := '1234567890abcdef'; // key length: 16 for AES-128, 32 for AES-256
var plainText := '敏感数据123';

// Encrypt
var encryptStr := aes.encode(plainText, key, 'CBC'); // mode: CBC or ECB
// Decrypt
var decryptStr := aes.decode(encryptStr, key, 'CBC');
writeln('加密后:' + encryptStr);
writeln('解密后:' + decryptStr);

Supported algorithms: AES, DES, 3DES, SM4; modes: ECB, CBC.

Logging & Debugging

logger.debug('调试信息');
logger.info('普通信息');
logger.warn('警告信息');
logger.error('错误信息');
logger.fatal('致命信息');

Log files are saved in the log/ directory, automatically named by date (e.g., 20260316.log), and retained for 30 days.

Error messages include line and column numbers for easy debugging. Example: {"code":500,"msg":"Script error: Unexpected \"=\" [line 42, column 4]"}

File Upload

The built‑in /upload interface requires no coding. Example HTML form:

<!DOCTYPE html>
<html>
<body>
<form action="http://localhost:8833/upload" method="post" enctype="multipart/form-data">
    Select file: <input type="file" name="file">
    <input type="submit" value="Upload">
</form>
</body>
</html>

Returns JSON: {"code":200,"data":"/up/20260319/14302512345678.png"}

Files are automatically organized by date in the uploads/ directory.

Version Information

  • Free Edition: Free forever, full functionality, suitable for personal/learning/small projects. Includes free updates and official tutorials/demos.
  • Commercial Edition: One‑time purchase, lifetime license, includes full Delphi source code, permanent technical support and upgrades.

Frequently Asked Questions

可能
IssuePossible CauseSolution
Console closes immediately after startup Port is occupied Change the Port setting in SrvConfig.ini to an unused port
404 Not Found when accessing a script Wrong script path, incorrect suffix, encoding not UTF-8 Ensure the script is in the script directory, the suffix matches, encoding is UTF‑8 without BOM, and the URL is correct
Database connection failed Database service not started, incorrect connection string Start the database service and check the connection string parameters (host, port, username, password)
Scheduled task not running Script not in task directory, malformed <task> block, service not running Move the script to task, check the block syntax, ensure the framework service is running
File upload fails No write permission on upload path, file too large, missing enctype in form Grant write permission to the uploads directory, check file size, add enctype="multipart/form-data" to the form
Script error "Undefined identifier" Syntax error, misspelled function name, missing include Check syntax, verify function names, include the necessary common script

API Quick Reference

Basic API

  • writeln(content): Output content to the page (supports HTML, JSON, text)
  • include(path): Include another script file
  • logger.level(content): Output log; levels: debug/info/warn/error/fatal

Database API

  • db.conn(connectionName, connectionString): Connect to database
  • db.query(connectionName, sql, parameters...): Query, returns JSON with data field
  • db.exec(connectionName, sql, parameters...): Insert/update/delete, returns JSON with rowcount field

HTTP Client API

  • http.get(url, header, params, reqEnc, resEnc, timeout): GET request
  • http.post(url, header, params, reqEnc, resEnc, timeout): POST form
  • http.json(url, header, params, reqEnc, resEnc, timeout): POST JSON
  • http.put(url, header, params, reqEnc, resEnc, timeout): PUT request
  • http.delete(url, header, params, reqEnc, resEnc, timeout): DELETE request
  • http.formdata(url, header, params): Form upload (supports files)
  • http.getfile(url): Download remote file to server's uploads directory, returns /up/... path

Global Variables API

  • WriteGlobalVar(name, value): Write a global variable
  • ReadGlobalVar(name): Read a global variable
  • ReadGlobalVarDef(name, defaultValue): Read a global variable; returns default if not exists
  • DeleteGlobalVar(name): Delete a global variable
  • GlobalVarsNames(pattern): List variable names (supports * wildcard)
  • CleanupGlobalVars: Clear all global variables

Utility API

  • captcha(content, quality): Generate captcha image data URL
  • QRCode(content, quality, scale): Generate QR code image data URL
  • FormatCapacity(bytes): Format storage capacity (1GB = 1000MB)
  • ByteSizeToStr(bytes): Format memory capacity (1GiB = 1024MiB)
  • Snowflake(datacenterId, workerId): Generate a unique distributed ID (IDs range 0..31)