Skip to content

⚡ 基础能力 ​

涵盖路由定义、参数解析、响应处理、静态文件托管、CORS跨域和Cookie管理等核心HTTP服务能力。

1. 路由控制与请求参数解析 ​

PicoServer 支持四种路由解析风格:精准路由、星号通配路由、RESTful 风格路由、特性路由。

csharp
private static readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    // 1. 精准路由(优先级最高)
    MyAPI.AddRoute("/api/user/query", QueryUser, "GET");
    MyAPI.AddRoute("/api/user/save", SaveUser, "POST");
    MyAPI.AddRoute("/api/user/json", SaveUserJson, "POST");

    // 2. 星号通配符路由(每段 URL 仅支持一个 *,支持多段通配,内置防目录遍历攻击)
    MyAPI.AddRoute("/api/*/posts", HandleWildcardPost, "POST");
    MyAPI.AddRoute("/api/*/user/*/detail", HandleMultiWildcard, "GET");

    MyAPI.StartServer();
    Console.WriteLine("服务已启动 http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 📥 处理 GET 查询参数:/api/user/query?name=xyz&age=18
private static async Task QueryUser(HttpListenerRequest request, HttpListenerResponse response)
{
    string name = request.GetQuery("name");
    int age = request.GetQuery<int>("age");
    bool isVip = request.GetQuery<bool>("isVip");

    await response.WriteAsync($"{{\"code\": 1, \"msg\": \"参数解析成功\", \"data\": {{ \"name\": \"{name}\", \"age\": {age} }} }}");
}

// 📥 处理 POST Form 表单:Content-Type: application/x-www-form-urlencoded
private static async Task SaveUser(HttpListenerRequest request, HttpListenerResponse response)
{
    var formData = request.ParseForm();
    string userName = formData["userName"];

    await response.WriteAsync($"{{\"code\":1, \"msg\":\"表单保存成功\",\"userName\":\"{userName}\"}}");
}

// 📥 处理 POST JSON 请求:Content-Type: application/json
private static async Task SaveUserJson(HttpListenerRequest request, HttpListenerResponse response)
{
    string bodyJson = await request.ReadBodyAsStringAsync();
    await response.WriteAsync($"{{\"code\":1, \"msg\":\"JSON保存成功\",\"data\":{bodyJson}}}");
}

// 处理单层星号通配符 POST 请求
private static async Task HandleWildcardPost(HttpListenerRequest request, HttpListenerResponse response)
{
    string requestUrl = request.Url.AbsolutePath;
    string bodyJson = await request.ReadBodyAsStringAsync();
    await response.WriteAsync($@"{{""code"":1,""msg"":""通配符匹配成功"",""requestUrl"":""{requestUrl}"",""data"":{bodyJson}}}");
}

// 处理多层星号通配符 GET 请求
private static async Task HandleMultiWildcard(HttpListenerRequest request, HttpListenerResponse response)
{
    string requestUrl = request.Url.AbsolutePath;
    await response.WriteAsync($@"{{""code"":1,""msg"":""多层通配匹配成功"",""requestUrl"":""{requestUrl}""}}");
}
vb
Private Shared ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    ' 1. 精准路由(优先级最高)
    MyAPI.AddRoute("/api/user/query", AddressOf QueryUser, "GET")
    MyAPI.AddRoute("/api/user/save", AddressOf SaveUser, "POST")
    MyAPI.AddRoute("/api/user/json", AddressOf SaveUserJson, "POST")

    ' 2. 星号通配符路由(每段 URL 仅支持一个 *,支持多段通配,内置防目录遍历攻击)
    MyAPI.AddRoute("/api/*/posts", AddressOf HandleWildcardPost, "POST")
    MyAPI.AddRoute("/api/*/user/*/detail", AddressOf HandleMultiWildcard, "GET")

    MyAPI.StartServer()
    Console.WriteLine("服务已启动 http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 📥 处理 GET 查询参数:/api/user/query?name=xyz&age=18
Private Async Function QueryUser(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim name As String = request.GetQuery("name")
    Dim age As Integer = request.GetQuery(Of Integer)("age")
    Dim isVip As Boolean = request.GetQuery(Of Boolean)("isVip")

    Await response.WriteAsync($"{{""code"": 1, ""msg"": ""参数解析成功"", ""data"": {{ ""name"": ""{name}"", ""age"": {age} }} }}")
End Function

' 📥 处理 POST Form 表单:Content-Type: application/x-www-form-urlencoded
Private Async Function SaveUser(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim formData = request.ParseForm()
    Dim userName As String = formData("userName")

    Await response.WriteAsync($"{{""code"":1, ""msg"":""表单保存成功"",""userName"":""{userName}""}}")
End Function

' 📥 处理 POST JSON 请求:Content-Type: application/json
Private Async Function SaveUserJson(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim bodyJson As String = Await request.ReadBodyAsStringAsync()
    Await response.WriteAsync($"{{""code"":1, ""msg"":""JSON保存成功"",""data"":{bodyJson}}}")
End Function

' 处理单层星号通配符 POST 请求
Private Async Function HandleWildcardPost(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim requestUrl As String = request.Url.AbsolutePath
    Dim bodyJson As String = Await request.ReadBodyAsStringAsync()
    Await response.WriteAsync($"{{""code"":1,""msg"":""通配符匹配成功"",""requestUrl"":""{requestUrl}"",""data"":{bodyJson}}}")
End Function

' 处理多层星号通配符 GET 请求
Private Async Function HandleMultiWildcard(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim requestUrl As String = request.Url.AbsolutePath
    Await response.WriteAsync($"{{""code"":1,""msg"":""多层通配匹配成功"",""requestUrl"":""{requestUrl}""}}")
End Function

参数解析相关扩展方法 ​

csharp
request.GetQuery();              // 获取查询字符串,不存在返回 null
request.GetQuery<T>();           // 自动转型读取查询字符串,失败返回默认值
request.ParseForm();             // 强类型解析 Form 表单字典
request.ReadBodyAsStringAsync(); // 流式读取 Body 文本(常用于 JSON)
request.Items();                 // 请求上下文属性字典,用于中间件传值
vb
request.GetQuery()              ' 获取查询字符串,不存在返回 null
request.GetQuery(Of T)()        ' 自动转型读取查询字符串,失败返回默认值
request.ParseForm()             ' 强类型解析 Form 表单字典
request.ReadBodyAsStringAsync() ' 流式读取 Body 文本(常用于 JSON)
request.Items()                 ' 请求上下文属性字典,用于中间件传值

2. RESTful 风格与 MIME 类型决议 ​

通过判断请求的 HttpMethod,可在单一路由内完成完整的 RESTful 资源分发。

csharp
private static readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/users", Users);
    MyAPI.StartServer();
    Console.WriteLine("服务已启动:http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

private static async Task Users(HttpListenerRequest request, HttpListenerResponse response)
{
    response.ContentType = GetContentType(".json"); // 自动获取标准 MIME 类型

    switch (request.HttpMethod)
    {
        case "GET":
            await response.WriteAsync(@"{""code"":1,""msg"":""获取用户成功""}");
            break;
        case "POST":
            response.StatusCode = 201;
            await response.WriteAsync(@"{""code"":1,""msg"":""创建用户成功""}");
            break;
        default:
            response.StatusCode = 405;
            await response.WriteAsync(@"{""code"":0,""msg"":""Method Not Allowed""}");
            break;
    }
}
vb
Private Shared ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/users", AddressOf Users)
    MyAPI.StartServer()
    Console.WriteLine("服务已启动:http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

Private Async Function Users(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.ContentType = GetContentType(".json")

    Select Case request.HttpMethod
        Case "GET"
            Await response.WriteAsync("{""code"":1,""msg"":""获取用户成功""}")
        Case "POST"
            response.StatusCode = 201
            Await response.WriteAsync("{""code"":1,""msg"":""创建用户成功""}")
        Case Else
            response.StatusCode = 405
            Await response.WriteAsync("{""code"":0,""msg"":""Method Not Allowed""}")
    End Select
End Function

MIME 类型内置决议

跨平台通用方法 GetContentType(".ext") 在 Windows/Linux/Docker 容器下的解析结果行为严格一致。默认针对文本资源追加 charset=UTF-8。支持多达 30+ 种常用扩展名(如视频流 .m3u8、.ts,字体 .woff2 等),未知类型默认回退为安全流 application/octet-stream。

3. 静态文件托管与 CORS 跨域 ​

静态文件(HTML/CSS/JS/图片/视频)托管配置,适配前端页面直接访问、静态资源服务等场景。

csharp
private static readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    // 添加静态文件服务(默认开启 ETag 智能缓存协商机制)
    MyAPI.AddStaticFiles("/", "wwwroot");
    // 自定义缓存周期:托管 "www" 文件夹至 "/web" 路由,浏览器缓存 30 天
    // MyAPI.AddStaticFiles("/web", "www", 2592000);

    // 开启全域 CORS 跨域支持
    MyAPI.AddCors();
    // MyAPI.AddCors("picoserver.cn"); // 亦可指定特定安全域名

    MyAPI.StartServer();
    Console.WriteLine("静态文件服务已启动:http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}
vb
Private Shared ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    ' 添加静态文件服务(默认开启 ETag 智能缓存协商机制)
    MyAPI.AddStaticFiles("/", "wwwroot")
    ' 自定义缓存周期:托管 "www" 文件夹至 "/web" 路由,浏览器缓存 30 天
    ' MyAPI.AddStaticFiles("/web", "www", 2592000)

    ' 开启全域 CORS 跨域支持
    MyAPI.AddCors()
    ' MyAPI.AddCors("picoserver.cn") ' 亦可指定特定安全域名

    MyAPI.StartServer()
    Console.WriteLine("静态文件服务已启动:http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

相关方法

csharp
MyAPI.AddStaticFiles("/", "wwwroot");              // 默认开启自动识别缓存
MyAPI.AddStaticFiles("/web", "www", 2592000);      // 缓存30天
MyAPI.AddCors();                                   // 启用跨域
MyAPI.AddCors("picoserver.cn");                    // 指定域名跨域

4. 语义化路由与服务控制 ​

语义化路由(1.7+) ​

csharp
MyAPI.MapGet("/api/user", GetUser);         // GET 请求
MyAPI.MapPost("/api/user", CreateUser);     // POST 请求
MyAPI.MapPut("/api/user/{id}", UpdateUser); // PUT 请求
MyAPI.MapDelete("/api/user/{id}", DeleteUser); // DELETE 请求
vb
MyAPI.MapGet("/api/user", AddressOf GetUser)
MyAPI.MapPost("/api/user", AddressOf CreateUser)
MyAPI.MapPut("/api/user/{id}", AddressOf UpdateUser)
MyAPI.MapDelete("/api/user/{id}", AddressOf DeleteUser)

服务控制方法 ​

StartServer 支持指定主机 / IP(1.7.7+),用于限定服务监听的网卡与访问范围。

csharp
MyAPI.StartServer();                        // 开启服务,默认端口 8090,监听所有地址
MyAPI.StartServer(8891);                    // 开启服务,指定端口,监听所有地址
MyAPI.StartServer("127.0.0.1");             // 限定本机访问
MyAPI.StartServer("127.0.0.1", 8891);       // 限定本机 + 指定端口
MyAPI.StartServer("192.168.1.100", 8891);   // 限定内网指定网卡访问
MyAPI.StopServer();                         // 停止服务

内置防空指针引用的安全读写机制。

csharp
private static readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/cookie/set", SetCookie, "GET");
    MyAPI.AddRoute("/cookie/get", GetCookie, "GET");
    MyAPI.AddRoute("/cookie/delete", DeleteCookie, "GET");
    MyAPI.AddRoute("/cookie/clear", ClearCookies, "GET");

    MyAPI.StartServer(8090);
    Console.WriteLine("Cookie 测试服务已启动:http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 设置 Cookie(支持过期时间、路径、HttpOnly)
private static async Task SetCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    response.AppendCookie("token", "pico_1234567", new CookieOptions
    {
        Expires = DateTimeOffset.Now.AddHours(1),
        Path = "/",
        HttpOnly = true
    });
    response.BuildCookie(); // 多 Cookie 需调用拼接
    await response.WriteAsync(@"{""code"":1, ""msg"":""Cookie 设置成功""}");
}

// 读取 Cookie
private static async Task GetCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    string token;
    request.TryGetCookieValue("token", out token);
    await response.WriteAsync($@"{{""code"":1, ""token"":""{token}""}}");
}

// 删除指定 Cookie
private static async Task DeleteCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    response.DeleteCookie("token", new CookieOptions { Path = "/" });
    await response.WriteAsync(@"{""code"":1, ""msg"":""Token Cookie 删除成功""}");
}

// 批量清理所有 Cookie
private static async Task ClearCookies(HttpListenerRequest request, HttpListenerResponse response)
{
    response.ClearCookies();
    await response.WriteAsync(@"{""code"":1, ""msg"":""所有 Cookie 已清理""}");
}
vb
Private Shared ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/cookie/set", AddressOf SetCookie, "GET")
    MyAPI.AddRoute("/cookie/get", AddressOf GetCookie, "GET")
    MyAPI.AddRoute("/cookie/delete", AddressOf DeleteCookie, "GET")
    MyAPI.AddRoute("/cookie/clear", AddressOf ClearCookies, "GET")

    MyAPI.StartServer(8090)
    Console.WriteLine("Cookie 测试服务已启动:http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

Private Async Function SetCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.AppendCookie("token", "pico_1234567", New CookieOptions With {
        .Expires = DateTimeOffset.Now.AddHours(1),
        .Path = "/",
        .HttpOnly = True
    })
    response.BuildCookie()
    Await response.WriteAsync("{""code"":1, ""msg"":""Cookie 设置成功""}")
End Function

Private Async Function GetCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim token As String
    request.TryGetCookieValue("token", token)
    Await response.WriteAsync($"{{\""code\"":1, \""token\"":\""{token}\""}}")
End Function

Private Async Function DeleteCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.DeleteCookie("token", New CookieOptions With { .Path = "/" })
    Await response.WriteAsync("{""code"":1, ""msg"":""Token Cookie 删除成功""}")
End Function

Private Async Function ClearCookies(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.ClearCookies()
    Await response.WriteAsync("{""code"":1, ""msg"":""所有 Cookie 已清理""}")
End Function

6. 跨域配置(CORS) ​

解决前后端分离跨域限制,支持极简配置。

csharp
MyAPI.AddCors();                    // 启用跨域,默认允许所有来源/方法/请求头
MyAPI.AddCors("picoserver.cn");     // 指定允许的域名
vb
MyAPI.AddCors()                    ' 启用跨域,默认允许所有来源/方法/请求头
MyAPI.AddCors("picoserver.cn")     ' 指定允许的域名