Skip to content

中间件系统详解

简介

中间件是 HttpServer 的请求/响应处理管道中的拦截器,可以在请求到达控制器之前和响应发送给客户端之后执行自定义逻辑。

请求流程:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Request   │ -> │    前置     │ -> │   控制器    │ -> │    后置     │ -> Response
│   到达      │    │   中间件    │    │    处理     │    │   中间件    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

中间件类型

类型执行时机
前置中间件cHttpServerRouteBefore路由匹配前
后置中间件cHttpServerRouterAfter控制器处理后

前置中间件 (RouteBefore)

基本结构

vb
' cAuthMiddleware.cls
Option Explicit

Public Sub Entry(ctx As cHttpServerContext)
    ' 中间件逻辑
    
    ' 终止后续处理
    ' ctx.fIsAbort = True
    
    ' 跳过其他中间件
    ' ctx.fIsSkipNextMiddleWare = True
End Sub

常用中间件示例

1. 登录验证中间件

vb
' cAuthCheckMiddleware.cls
Option Explicit

Public Sub Entry(ctx As cHttpServerContext)
    ' 排除登录接口
    If ctx.Request.PathInfo = "/login" Then Exit Sub
    If ctx.Request.PathInfo = "/register" Then Exit Sub
    
    ' 检查 Session
    If Not ctx.Session.Exists("user_id") Then
        ctx.Response.State401 "请先登录"
        ctx.fIsAbort = True  ' 终止后续处理
    End If
End Sub

2. IP 黑名单中间件

vb
' cIPBlacklistMiddleware.cls
Option Explicit

Dim Blacklist As Scripting.Dictionary

Private Sub Class_Initialize()
    Set Blacklist = New Scripting.Dictionary
    Blacklist("192.168.1.100") = True
    Blacklist("10.0.0.50") = True
End Sub

Public Sub Entry(ctx As cHttpServerContext)
    Dim clientIP As String
    clientIP = ctx.ClientInfo.IP
    
    If Blacklist.Exists(clientIP) Then
        ctx.Response.State403 "您的IP已被封禁"
        ctx.fIsAbort = True
    End If
End Sub

3. 请求日志中间件

vb
' cRequestLogMiddleware.cls
Option Explicit

Public Sub Entry(ctx As cHttpServerContext)
    Dim log As String
    log = Now & " " & _
          ctx.ClientInfo.IP & " " & _
          ctx.Request.MethodName & " " & _
          ctx.Request.PathInfo
    
    ' 写入日志文件
    Call WriteLog(log)
    
    ' 在上下文中记录开始时间(用于计算响应时间)
    ctx.fStartTime = Timer
End Sub

Private Sub WriteLog(msg As String)
    Dim f As Integer
    f = FreeFile
    Open "C:\Logs\access.log" For Append As #f
    Print #f, msg
    Close #f
End Sub

4. CORS 预检处理

vb
' cCorsMiddleware.cls
Option Explicit

Public Sub Entry(ctx As cHttpServerContext)
    ' 处理 OPTIONS 预检请求
    If ctx.Request.Method = ReqOptions Then
        ctx.Response.Header("Access-Control-Allow-Origin") = "*"
        ctx.Response.Header("Access-Control-Allow-Methods") = "GET, POST, PUT, DELETE, OPTIONS"
        ctx.Response.Header("Access-Control-Allow-Headers") = "Content-Type, Authorization"
        ctx.Response.Text ""
        ctx.fIsAbort = True
    End If
End Sub

5. 请求频率限制

vb
' cRateLimitMiddleware.cls
Option Explicit

Dim RequestCounts As Scripting.Dictionary
Dim LastReset As Date

Private Sub Class_Initialize()
    Set RequestCounts = New Scripting.Dictionary
    LastReset = Now
End Sub

Public Sub Entry(ctx As cHttpServerContext)
    ' 每分钟重置计数
    If DateDiff("n", LastReset, Now) >= 1 Then
        Set RequestCounts = New Scripting.Dictionary
        LastReset = Now
    End If
    
    Dim clientIP As String
    clientIP = ctx.ClientInfo.IP
    
    ' 统计请求次数
    If Not RequestCounts.Exists(clientIP) Then
        RequestCounts(clientIP) = 0
    End If
    RequestCounts(clientIP) = RequestCounts(clientIP) + 1
    
    ' 限制每分钟 100 次
    If RequestCounts(clientIP) > 100 Then
        ctx.Response.State429 "请求过于频繁,请稍后再试"
        ctx.fIsAbort = True
    End If
End Sub

中间件注册与优先级

vb
Private Sub Form_Load()
    Set Server = New cHttpServer
    
    ' 注册中间件(按优先级顺序)
    Call Server.RouteBefore.Add("cors", New cCorsMiddleware)          ' 第1个执行
    Call Server.RouteBefore.Add("ratelimit", New cRateLimitMiddleware) ' 第2个执行
    Call Server.RouteBefore.Add("ipblacklist", New cIPBlacklistMiddleware) ' 第3个执行
    Call Server.RouteBefore.Add("requestlog", New cRequestLogMiddleware)   ' 第4个执行
    Call Server.RouteBefore.Add("authcheck", New cAuthCheckMiddleware)     ' 第5个执行
    
    ' 注册控制器
    Call Server.Router.Reg("Api", New cApiController)
    Call Server.Router.Add("/api/data", "Api@Data")
    
    Call Server.Start(8080)
End Sub

上下文控制标志

标志说明
ctx.fIsAbort设为 True 终止整个请求处理
ctx.fIsSkipNextMiddleWare设为 True 跳过后续中间件

后置中间件 (RouteAfter)

后置中间件用于响应发送后的处理(当前版本为预留接口)。

vb
' cResponseLogMiddleware.cls
Option Explicit

Public Sub Entry(ctx As cHttpServerContext)
    ' 计算响应时间
    If ctx.fStartTime > 0 Then
        Dim elapsed As Double
        elapsed = Timer - ctx.fStartTime
        
        ' 记录慢请求
        If elapsed > 1 Then
            Call WriteSlowLog(ctx.Request.PathInfo & " 耗时 " & elapsed & " 秒")
        End If
    End If
End Sub

上下文扩展

可以在上下文中添加自定义属性供中间件和控制器共享:

vb
' cHttpServerContext 扩展模块

' 在 MiddleWare 中设置
Public Sub AuthMiddleware(ctx As cHttpServerContext)
    If IsValidToken Then
        ctx.fUserId = GetUserIdFromToken()
        ctx.fUserRole = GetUserRole()
    End If
End Sub

' 在控制器中使用
Public Sub GetData(ctx As cHttpServerContext)
    ' 获取中间件设置的信息
    Dim userId As String
    userId = ctx.fUserId
    
    ' 根据角色返回不同数据
    If ctx.fUserRole = "admin" Then
        ' 返回所有数据
    Else
        ' 返回部分数据
    End If
End Sub

中间件链执行顺序

请求: GET /api/users

1. cCorsMiddleware          -> 通过
2. cRateLimitMiddleware     -> 通过
3. cIPBlacklistMiddleware   -> 通过
4. cRequestLogMiddleware    -> 通过
5. cAuthCheckMiddleware     -> 检查 Session
   └─> 未登录 -> ctx.fIsAbort = True
   
请求被终止,返回 401

最后更新: 2026-05-17

VB6及其LOGO版权为微软公司所有