Complete API reference, deployment guide, FAQ
Get started with WebPascal 5 in 10 minutes.
Download the package from the official website and extract it to any directory.
Edit SrvConfig.ini to set port (default 8833), CORS, GZip, etc.
Double‑click webpascal.exe; the console shows Server started on port 8833 when successful.
Create script/hello.api with:
// Hello World example
writeln('Hello WebPascal 5!');
writeln('The exclusive web development tool for Delphi developers!');Access http://localhost:8833/ask/hello.api to see the output.
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)
Core settings in SrvConfig.ini:
Port=8833 # Port number
CORS=1 # Enable CORS (1) or disable (0)
GZip=1 # Enable GZip compression (1) or disable (0)
UpDir=.\Uploads # Upload directory
Use nssm to register webpascal.exe as a Windows service.
Fully compatible with Delphi native syntax:
var i: Integer; s: string;for, while, repeat‑untilif‑else, casewriteln, FormatDateTime, IntToStr, Trim//, { }, (* *)Modularization: include('common.api');
// 1. Parse JSON string
var jsonStr := '{"name":"张三","age":18,"gender":"男"}';
var obj := json.parse(jsonStr);
// 2. Get JSON values (support default operator ?? to avoid null errors)
var name := obj.name; // directly get, returns null if key missing
var email := obj.email ?? '未设置'; // return default if key missing
// 3. Modify JSON object
obj.age := int(20);
// 4. JSON object to string
var newJsonStr := json.stringify(obj);
writeln(newJsonStr);
writeln(unicodetoansi(newJsonStr));
// 5. Iterate JSON object
for var i := 0 to obj.length() - 1 do
begin
writeln(obj.ElementName(i) + ' : ' + obj[i] + ' | ' + obj[i].TypeName());
end;// 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);// 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);// 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');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
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);Built-in HTTP client supports common request methods:
var getResult := http.get('https://api.example.com/users?id=123', '', '');
writeln(getResult);var postResult := http.post('https://api.example.com/users', '', 'name=张三&age=18');
writeln(postResult);var jsonData := '{"name":"张三","age":18}';
var jsonResult := http.json('https://api.example.com/users', '', jsonData);
writeln(jsonResult);var putResult := http.put('https://api.example.com/users/123', '', 'name=李四');
writeln(putResult);var deleteResult := http.delete('https://api.example.com/users/123', '', '');
writeln(deleteResult);var uploadResult := http.formdata(
'https://api.example.com/upload',
'Authorization: Bearer token',
'filename=file(/local/image.jpg)'
);
writeln(uploadResult);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.
var result := http.get(
'https://api.example.com',
'',
'',
'utf8', // request encoding
'utf8', // response encoding
5000 // timeout in milliseconds
);Note: Encoding parameter uses 'utf8' (without hyphen).
Create a script in the task directory and add a <task> configuration block at the top.
Schedule Modes:
time is the number of seconds, e.g., "10" means execute every 10 seconds.yyyyMMddHHmmss, e.g., "20180520000000" means execute at 2018-05-20 00:00:00.MMddHHmmss, e.g., "0520000000" means execute every year on May 20 at 00:00:00.ddHHmmss, e.g., "20000000" means execute on the 20th of each month at 00:00:00.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.
captcha('1234', 80) returns image data URLQRCode('https://webpascal.com', 80, 2)Now, FormatDateTime, UnixTime, LocalDateTimeToUnixTime, UnixTimeToLocalDateTimeSnowflake(1,2) generates unique IDByteSizeToStr(1024^3) → 1GiB; FormatCapacity(1024^3) → 1.07GBvar 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('令牌验证失败!');// 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.
// 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.
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]"}
The built-in /upload interface requires no coding. HTML form example:
<!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.
| Issue | Possible Cause | Solution |
|---|---|---|
| Script not accessible, "404 Not Found" | Wrong script path, incorrect suffix, encoding not UTF-8 | Ensure script is in script directory, suffix matches, encoding is UTF‑8 (no BOM), and URL format is correct |
| No output, but "200 OK" | Script did not output anything | Add writeln statements or use try..except..end |
| Database connection failed, "Cannot connect to server" | Database service not started, incorrect connection string | Start database service, check host, port, username, password in connection string |
| Scheduled task not running | Script not in task directory, <task> block malformed, service not running | Move script to task, check block syntax, ensure framework is running |
| File upload failed | No write permission on upload path, file too large, missing enctype in form | Grant write permission to uploads, check file size, add enctype="multipart/form-data" to form |
| Script error, "Undefined identifier" | Syntax error, misspelled function name, missing include | Check syntax, verify function names, include necessary common scripts |
writeln(content): Output content to the page (supports HTML, JSON, text)include(path): Include another script filelogger.level(content): Output log; levels: debug/info/warn/error/fataldb.conn(connectionName, connectionString): Connect to databasedb.query(connectionName, sql, parameters...): Query, returns JSON with data fielddb.exec(connectionName, sql, parameters...): Insert/update/delete, returns JSON with rowcount fieldhttp.get(url, header, params, reqEnc, resEnc, timeout): GET requesthttp.post(url, header, params, reqEnc, resEnc, timeout): POST formhttp.json(url, header, params, reqEnc, resEnc, timeout): POST JSONhttp.put(url, header, params, reqEnc, resEnc, timeout): PUT requesthttp.delete(url, header, params, reqEnc, resEnc, timeout): DELETE requesthttp.formdata(url, header, params): Form upload (supports files)http.getfile(url): Download remote file to server's uploads, returns /up/... pathcaptcha(content, quality): Generate captcha image data URLQRCode(content, quality, scale): Generate QR code image data URLFormatCapacity(bytes): Format storage capacity (1GB = 1000MB)ByteSizeToStr(bytes): Format memory capacity (1GiB = 1024MiB)Snowflake(datacenterId, workerId): Generate unique distributed ID (IDs range 0..31)