Skip to content

🔧 高级定制 ​

PicoServer 开放了中间件,可以借此进行二次开发、封装、集成解决方案等。

利用 AddMiddleware() 可开发属于自己的中间件。比如:参数路由、限流、黑名单等等。

注意:中间件的执行是按添加顺序执行的。

1. 自定义中间件 ​

极简文件服务器 ​

一个完整的文件服务器示例,展示如何组合路由与 SendFileAsync 实现文件浏览、预览和下载。

csharp
using PicoServer;

var MyAPI = new WebAPIServer();
string rootPath = @"D:\MyFiles";

MyAPI.AddRoute("/files", async (req, resp) => {
    var files = Directory.GetFiles(rootPath).Select(Path.GetFileName);
    var html = "<h1>文件清单</h1><ul>";
    foreach (var f in files)
        html += $"<li><a href='/view?name={f}'>{f}</a></li>";
    html += "</ul>";
    await resp.WriteAsync(html, WebAPIServer.ContentType.TextHtml);
}, "GET");

MyAPI.AddRoute("/view", (req, resp) => {
    string fileName = req.ParseGetQueryString("name");
    string fullPath = Path.Combine(rootPath, fileName);
    return resp.SendFileAsync(fullPath, asAttachment: false);
}, "GET");

MyAPI.AddRoute("/download", (req, resp) => {
    string fileName = req.ParseGetQueryString("name");
    return resp.SendFileAsync(Path.Combine(rootPath, fileName));
}, "GET");

MyAPI.StartServer(8090);
Console.WriteLine("文件服务器已启动: http://127.0.0.1:8090");
vb
Imports PicoServer

Dim MyAPI = New WebAPIServer()
Dim rootPath = "D:\MyFiles"

MyAPI.AddRoute("/files", Async Function(req, resp)
    Dim files = Directory.GetFiles(rootPath).[Select](Function(f) Path.GetFileName(f))
    Dim html = "<h1>文件清单</h1><ul>"
    For Each f In files
        html += $"<li><a href='/view?name={f}'>{f}</a></li>"
    Next
    html += "</ul>"
    Await resp.WriteAsync(html, WebAPIServer.ContentType.TextHtml)
End Function, "GET")

MyAPI.AddRoute("/view", Function(req, resp)
    Dim fileName = req.ParseGetQueryString("name")
    Dim fullPath = Path.Combine(rootPath, fileName)
    Return resp.SendFileAsync(fullPath, False)
End Function, "GET")

MyAPI.AddRoute("/download", Function(req, resp)
    Dim fileName = req.ParseGetQueryString("name")
    Return resp.SendFileAsync(Path.Combine(rootPath, fileName))
End Function, "GET")

MyAPI.StartServer(8090)
Console.WriteLine("文件服务器已启动: http://127.0.0.1:8090")

2. 动态路由处理器 ​

利用自定义中间件的扩展功能实现动态路由,在一个逻辑块内完成路径匹配、方法分发和请求终结。

csharp
using PicoServer;
using System.Text.RegularExpressions;

var MyAPI = new WebAPIServer();

MyAPI.AddMiddleware(async (req, resp) => {
    var match = Regex.Match(req.Url.AbsolutePath, @"^/product/(?<id>\d+)$");

    if (match.Success) {
        string id = match.Groups["id"].Value;

        switch (req.HttpMethod) {
            case "GET":
                await resp.WriteAsync($"{{\"action\":\"查询商品\", \"id\":{id}}}");
                break;
            case "POST":
                await resp.WriteAsync($"{{\"action\":\"更新商品\", \"id\":{id}, \"result\":\"Success\"}}");
                break;
            default:
                resp.StatusCode = 405;
                await resp.WriteAsync("{\"msg\":\"不支持的操作\"}");
                break;
        }

        return false;
    }

    return true;
});

MyAPI.StartServer(8090);
vb
Imports PicoServer
Imports System.Text.RegularExpressions

Dim MyAPI = New WebAPIServer()

MyAPI.AddMiddleware(Async Function(req, resp)
    Dim match = Regex.Match(req.Url.AbsolutePath, "^/product/(?<id>\d+)$")

    If match.Success Then
        Dim id = match.Groups("id").Value

        Select Case req.HttpMethod
            Case "GET"
                Await resp.WriteAsync($"{{\"action\":\"查询商品\", \"id\":{id}}}")
            Case "POST"
                Await resp.WriteAsync($"{{\"action\":\"更新商品\", \"id\":{id}, \"result\":\"Success\"}}")
            Case Else
                resp.StatusCode = 405
                Await resp.WriteAsync("{\"msg\":\"不支持的操作\"}")
        End Select

        Return False
    End If

    Return True
End Function)

MyAPI.StartServer(8090)

3. 扩展点 ​

中间件注册 ​

csharp
MyAPI.AddMiddleware(async (req, resp) => {
    // 自定义逻辑
    return true; // 返回 true 继续执行,返回 false 终结请求
});

服务事件 ​

csharp
MyAPI.OnServerStarted += () => { Console.WriteLine("服务已启动"); };
MyAPI.OnServerStopped += () => { Console.WriteLine("服务已停止"); };