Skip to content

🔧 Advanced Customization ​

PicoServer opens up middleware for secondary development, encapsulation, and solution integration.

Use AddMiddleware() to develop your own middleware such as parameter routing, rate limiting, blacklist, etc.

Note: Middleware executes in the order they are added.

1. Custom Middleware ​

Minimal File Server ​

A complete file server example combining routes and SendFileAsync for browsing, previewing and downloading.

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>File List</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("File server started: 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>File List</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("File server started: http://127.0.0.1:8090")

2. Dynamic Route Handler ​

Implement dynamic routing using middleware extension capabilities, completing path matching, method dispatching, and request termination in one logic block.

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\":\"Query Product\", \"id\":{id}}}");
                break;
            case "POST":
                await resp.WriteAsync($"{{\"action\":\"Update Product\", \"id\":{id}, \"result\":\"Success\"}}");
                break;
            default:
                resp.StatusCode = 405;
                await resp.WriteAsync("{\"msg\":\"Method not supported\"}");
                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\":\"Query Product\", \"id\":{id}}}")
            Case "POST"
                Await resp.WriteAsync($"{{\"action\":\"Update Product\", \"id\":{id}, \"result\":\"Success\"}}")
            Case Else
                resp.StatusCode = 405
                Await resp.WriteAsync("{\"msg\":\"Method not supported\"}")
        End Select

        Return False
    End If

    Return True
End Function)

MyAPI.StartServer(8090)

3. Extension Points ​

Middleware Registration ​

csharp
MyAPI.AddMiddleware(async (req, resp) => {
    // Custom logic
    return true; // Return true to continue, false to terminate
});

Service Events ​

csharp
MyAPI.OnServerStarted += () => { Console.WriteLine("Server started"); };
MyAPI.OnServerStopped += () => { Console.WriteLine("Server stopped"); };