网络编程
网络编程是现代应用开发的重要组成部分。本章将详细介绍 Sii 2 中的 HTTP 客户端和服务器功能,以及如何构建网络应用。
网络编程概述
Sii 2 通过运行时服务器提供网络编程能力,包括:
- HTTP 客户端:发送 HTTP 请求
- HTTP 服务器:创建 HTTP 服务器
- 路由处理:处理不同的 HTTP 路由
- 请求响应:处理 HTTP 请求和响应
HTTP 客户端
sii.get()
发送 GET 请求:
// 基本 GET 请求
let response: obj = sii.get("https://api.example.com/data");
// 访问响应数据
let status: int = response.status;
let body: obj = response.body;
let headers: obj = response.headers;
sii.post()
发送 POST 请求:
// POST 请求,发送 JSON 数据
crob data = new Object();
data.name = "Alice";
data.age = 25;
let response: obj = sii.post("https://api.example.com/users", data);
// 处理响应
if (response.status == 200) {
sii.io.print("User created successfully");
} else {
sii.io.print("Error: " + string(response.status));
}
HTTP 请求示例
func fetchUserData(userId: int): obj | void {
let url: string = "https://api.example.com/users/" + string(userId);
let response: obj = sii.get(url);
if (response.status == 200) {
back response.body;
} else {
sii.error("Failed to fetch user: " + string(response.status));
back;
}
}
// 使用
let user: obj | void = fetchUserData(123);
if (typeins(user) == "obj") {
let userData: obj = user as obj;
sii.io.print("User: " + userData.name);
}
HTTP 服务器
sii.listen()
创建 HTTP 服务器并监听端口:
// 监听端口 3000
sii.listen(3000);
// 服务器启动后,可以注册路由处理请求
路由注册
HTTP 路由通过 sii.get(), sii.post() 等方法注册,handler 参数是函数名字符串:
// 定义处理函数
func handleGetUsers(request: obj): obj {
crob response = new Object();
response.status = 200;
response.body = "User list";
back response;
}
func handleCreateUser(request: obj): obj {
let userData: obj = request.body;
// 处理用户创建逻辑
crob response = new Object();
response.status = 201;
response.body = "User created";
back response;
}
// 注册 GET 路由(handler 是函数名字符串)
sii.get("/users", "handleGetUsers");
// 注册 POST 路由
sii.post("/users", "handleCreateUser");
请求对象
请求对象包含以下信息:
func handleRequest(request: obj): obj {
// 请求方法
let method: string = request.method; // "GET", "POST", etc.
// 请求路径
let path: string = request.url;
// 请求头
let headers: obj = request.headers;
// 请求体(POST/PUT 请求)
let body: obj = request.body;
// 查询参数(如果支持)
// let query: obj = request.query;
// 处理请求...
crob response = new Object();
response.status = 200;
response.body = "OK";
back response;
}
响应对象
响应对象包含以下字段:
func createResponse(status: int, body: obj, headers: obj): obj {
crob response = new Object();
response.status = status;
response.body = body;
response.headers = headers;
back response;
}
响应辅助函数
sii.respText()
返回文本响应:
func handleTextRequest(request: obj): obj {
let response: obj = sii.respText(200, "Hello, World!");
back response;
}
sii.respJson()
返回 JSON 响应:
func handleJsonRequest(request: obj): obj {
crob data = new Object();
data.message = "Success";
data.timestamp = sii.now();
let response: obj = sii.respJson(200, data);
back response;
}
sii.respHtml()
返回 HTML 响应:
func handleHtmlRequest(request: obj): obj {
let html: string = "<html><body><h1>Hello, Sii 2!</h1></body></html>";
let response: obj = sii.respHtml(200, html);
back response;
}
完整 HTTP 服务器示例
示例 1:简单的 API 服务器
// 用户数据存储(简化版,实际应使用数据库)
let users: arr = new Array();
// 定义处理函数
func handleGetUsers(request: obj): obj {
back sii.respJson(200, users);
}
func handleGetUser(request: obj): obj {
// 注意:路径参数需要通过 request 对象获取
let userId: int = request.params.id.toInt();
// 查找用户(简化版)
let user: obj | void = findUser(userId);
if (typeins(user) == "obj") {
back sii.respJson(200, user as obj);
} else {
back sii.respText(404, "User not found");
}
}
func handleCreateUser(request: obj): obj {
let userData: obj = request.body;
// 验证数据
if (userData.name.length() == 0) {
back sii.respText(400, "Name is required");
}
// 创建用户
crob newUser = new Object();
newUser.id = users.length() + 1;
newUser.name = userData.name;
newUser.email = userData.email;
// 添加用户到数组
users[users.length()] = newUser;
back sii.respJson(201, newUser);
}
func handleUpdateUser(request: obj): obj {
let userId: int = request.params.id.toInt();
let userData: obj = request.body;
// 查找并更新用户
let user: obj | void = findUser(userId);
if (typeins(user) == "obj") {
let existingUser: obj = user as obj;
existingUser.name = userData.name;
existingUser.email = userData.email;
back sii.respJson(200, existingUser);
} else {
back sii.respText(404, "User not found");
}
}
func handleDeleteUser(request: obj): obj {
let userId: int = request.params.id.toInt();
// 删除用户(简化版)
let success: bool = deleteUser(userId);
if (success) {
back sii.respText(200, "User deleted");
} else {
back sii.respText(404, "User not found");
}
}
// 启动服务器
sii.listen(8080);
// 注册路由(handler 是函数名字符串)
sii.get("/users", "handleGetUsers");
sii.get("/users/:id", "handleGetUser");
sii.post("/users", "handleCreateUser");
sii.put("/users/:id", "handleUpdateUser");
sii.delete("/users/:id", "handleDeleteUser");
// 辅助函数
func findUser(id: int): obj | void {
forloop (let i: int = 0; i < users.length(); i.getUp(1)) {
let user: obj = users[i];
if (user.id == id) {
back user;
}
}
back;
}
func deleteUser(id: int): bool {
forloop (let i: int = 0; i < users.length(); i.getUp(1)) {
let user: obj = users[i];
if (user.id == id) {
rmv users[i]; // 使用 rmv 语句删除元素
back true;
}
}
back false;
}
示例 2:文件服务器
// 定义处理函数
func handleGetFile(request: obj): obj {
let filename: string = request.params.filename;
let filePath: string = sii.pathJoin("./files", filename);
if (!sii.exists(filePath)) {
back sii.respText(404, "File not found");
}
let content: string = sii.readText(filePath);
back sii.respText(200, content);
}
func handleSaveFile(request: obj): obj {
let filename: string = request.params.filename;
let filePath: string = sii.pathJoin("./files", filename);
let content: string = request.body.content;
sii.writeText(filePath, content);
back sii.respText(200, "File saved");
}
// 启动文件服务器
sii.listen(3000);
// 注册路由
sii.get("/files/:filename", "handleGetFile");
sii.post("/files/:filename", "handleSaveFile");
HTTP 客户端示例
示例 1:API 客户端
func fetchApiData(endpoint: string): obj | void {
let url: string = "https://api.example.com" + endpoint;
let response: obj = sii.get(url);
if (response.status == 200) {
back response.body;
} else {
sii.error("API request failed: " + string(response.status));
back;
}
}
// 使用
let data: obj | void = fetchApiData("/users");
if (typeins(data) == "obj") {
let users: arr = data.users as arr;
sii.io.print("Found " + string(users.length()) + " users");
}
示例 2:数据提交
func submitData(url: string, data: obj): bool {
let response: obj = sii.post(url, data);
if (response.status == 200 || response.status == 201) {
sii.log("Data submitted successfully");
back true;
} else {
sii.error("Failed to submit data: " + string(response.status));
back false;
}
}
// 使用
crob formData = new Object();
formData.name = "Alice";
formData.email = "alice@example.com";
let success: bool = submitData("https://api.example.com/submit", formData);
错误处理
HTTP 错误处理
func safeHttpGet(url: string): obj | void {
let response: obj = sii.get(url);
if (response.status >= 200 && response.status < 300) {
back response.body;
} else if (response.status == 404) {
sii.error("Resource not found: " + url);
back;
} else if (response.status >= 500) {
sii.error("Server error: " + string(response.status));
back;
} else {
sii.error("Request failed: " + string(response.status));
back;
}
}
超时处理
// 注意:Sii 2 可能不直接支持超时设置
// 需要在运行时服务器层面处理
func requestWithTimeout(url: string, timeoutMs: int): obj | void {
// 实现超时逻辑(如果支持)
let response: obj = sii.get(url);
back response;
}
网络编程最佳实践
1. 错误处理
始终检查 HTTP 响应状态:
func safeHttpRequest(url: string): obj | void {
let response: obj = sii.get(url);
if (response.status != 200) {
sii.error("HTTP Error: " + string(response.status));
back;
}
back response.body;
}
2. 请求验证
验证请求数据:
func validateRequest(request: obj): bool {
if (request.method == "POST" || request.method == "PUT") {
if (typeins(request.body) != "obj") {
back false;
}
}
back true;
}
3. 响应格式化
使用统一的响应格式:
func createApiResponse(success: bool, data: obj, message: string): obj {
crob response = new Object();
response.success = success;
response.data = data;
response.message = message;
response.timestamp = sii.now();
back sii.respJson(if (success) { 200 } else { 400 }, response);
}
4. 路由组织
按功能组织路由:
// users.sii - 用户相关路由
func setupUserRoutes(): void {
sii.get("/users", "handleGetUsers");
sii.post("/users", "handleCreateUser");
sii.get("/users/:id", "handleGetUser");
sii.put("/users/:id", "handleUpdateUser");
sii.delete("/users/:id", "handleDeleteUser");
}
// main.sii
setupUserRoutes();
sii.listen(8080);
小结
本章介绍了 Sii 2 中的网络编程:
- HTTP 客户端:
get(),post()等请求方法 - HTTP 服务器:
listen(),route()创建服务器 - 请求处理:处理 HTTP 请求和响应
- 响应辅助:
respText(),respJson(),respHtml() - 错误处理:HTTP 错误处理机制
- 最佳实践:如何构建健壮的网络应用
下一章我们将学习编译和构建,了解如何使用 Sii 2 编译器。