Skip to content

Ccxc.Core.HttpServer 包

Ccxc.Core.HttpServer 是一个基于 ASP.NET Core Kestrel 的轻量级 HTTP 服务器框架,提供了简化的 Web API 开发体验。该包支持控制器注册、路由匹配、中间件、CORS、参数验证等功能。

命名空间结构

  • Ccxc.Core.HttpServer - 核心HTTP服务器类
  • Ccxc.Core.HttpServer.Middlewares - 中间件功能

核心类

Server 类

HTTP 服务器的核心类,基于 Kestrel 提供 HTTP 服务。

csharp
public class Server

构造函数

csharp
public Server(int port, string prefix = "")

参数:

  • port (int): 监听的端口号
  • prefix (string, 可选): 服务提供的路径前缀,如传入 "api" 会在 http://ip:port/api 下提供服务

属性

属性名类型描述
HostIWebHost运行中的 WebHost 实例
DebugModebool调试模式开关,控制异常信息的详细程度

静态方法

方法名返回类型描述
GetServer(int, string)Server获取 HTTP 服务器实例
RegisterController<T>()void注册控制器类
RegisterController(object)void注册控制器对象
RegisterController(Type)void注册控制器类型
RegisterHandler(HttpHandler)void注册 HTTP 处理器
RegisterHandler(IEnumerable<HttpHandler>)void批量注册 HTTP 处理器
RegisterHandler(string, string, Func<Request, Response, Task>)void注册 HTTP 处理方法
AddMiddleware(Func<HttpContext, Func<Task>, Task>)void添加中间件
GetInterfaces()List<string>获取所有已注册的接口列表

实例方法

方法名返回类型描述
Run()Task启动 HTTP 服务器
Stop()Task停止服务器运行
Register(HttpHandler)Server注册处理器(链式调用)
Register(string, string, Func<Request, Response, Task>)Server注册处理方法(链式调用)
Use(Func<HttpContext, Func<Task>, Task>)Server添加中间件(链式调用)

HTTP 处理相关类

HttpController 类

HTTP 控制器基类,所有控制器都必须继承此类。

csharp
public class HttpController
{
}

HttpHandlerAttribute 特性

用于标记控制器方法为 HTTP 处理方法的特性。

csharp
public class HttpHandlerAttribute : Attribute

属性

属性名类型描述
MethodstringHTTP 方法,如 GET、POST、PUT 等
Pathstring路径,必须以 "/" 开头

构造函数

csharp
public HttpHandlerAttribute(string method, string path)

参数:

  • method (string): HTTP 方法名
  • path (string): 匹配的路径

HttpHandler 类

HTTP 处理器类,封装路由和处理逻辑。

csharp
public class HttpHandler

属性

属性名类型描述
MethodstringHTTP 方法
Pathstring路径模式
HandlerFunc<Request, Response, Task>处理方法

请求响应类

Request 类

HTTP 请求封装类,提供便捷的请求数据访问。

csharp
public class Request

构造函数

csharp
public Request(HttpRequest request, dynamic pathParam = null)

参数:

  • request (HttpRequest): 原始 HTTP 请求
  • pathParam (dynamic, 可选): 路径参数

属性

属性名类型描述
RawRequestHttpRequest原始 ASP.NET Core 请求对象
Paramsdynamic路径参数(如 :id 匹配的值)
Querydynamic查询字符串参数
Headerdynamic请求头信息
BodyStringstring请求体字符串
FormdynamicPOST 表单数据
ContextItemsIDictionary<object, object>上下文项目

方法

方法名返回类型描述
Json<T>()T将请求体反序列化为指定类型的对象

Response 类

HTTP 响应封装类,提供便捷的响应发送方法。

csharp
public class Response

构造函数

csharp
public Response(HttpResponse response)

参数:

  • response (HttpResponse): 原始 HTTP 响应

属性

属性名类型描述
RawResponseHttpResponse原始 ASP.NET Core 响应对象

方法

方法名返回类型描述
SetHeader(string, string)void设置响应头
JsonResponse(int, object)Task发送 JSON 响应
StringResponse(int, string, string)Task发送字符串响应
BinaryResponse(int, byte[], string)Task发送二进制响应

静态方法

方法名返回类型描述
SimpleResponse(HttpResponse, int, string, string)Task发送简单响应

路由系统

Router 类(内部类)

路由匹配工具类。

csharp
internal class Router

静态方法

方法名返回类型描述
Match(string, string, out dynamic)bool匹配请求路径与处理器路径

路径匹配规则:

  • 完全匹配:/api/users 只匹配 /api/users
  • 参数匹配:/api/users/:id 匹配 /api/users/123,参数 id 值为 123
  • 支持多个参数:/api/users/:id/posts/:postId

中间件

Cors 类

CORS(跨域资源共享)中间件。

csharp
public static class Cors

扩展方法

方法名返回类型描述
UseCors(this Server)Server启用 CORS 支持

CORS 配置:

  • 允许所有源:Access-Control-Allow-Origin: *
  • 允许的方法:GET, POST, PUT, DELETE
  • 允许的头部:Content-Type, User-Token, X-Requested-With, X-Auth-Token, Upload-Token, X-Captcha-Nonce
  • 预检缓存时间:600 秒

验证系统

Validation 类

请求参数验证工具类。

csharp
public static class Validation

静态方法

方法名返回类型描述
Valid<T>(T, out string)bool验证模型,返回验证结果和错误信息

RequiredAttribute 特性

标记属性为必需的验证特性。

csharp
public class RequiredAttribute : Attribute

属性

属性名类型描述
Messagestring自定义错误消息

异常类

HttpHandlerRegisterException

HTTP 处理器注册异常。

csharp
internal class HttpHandlerRegisterException : Exception

使用示例

基本服务器设置

csharp
// 创建服务器实例
var server = Server.GetServer(8080, "api");

// 启用 CORS
server.UseCors();

// 添加自定义中间件
server.Use(async (context, next) =>
{
    // 日志记录
    Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
    await next();
});

// 启动服务器
await server.Run();

控制器方式

csharp
public class UserController : HttpController
{
    [HttpHandler("GET", "/users")]
    public async Task GetUsers(Request request, Response response)
    {
        var users = GetAllUsers(); // 业务逻辑
        await response.JsonResponse(200, users);
    }

    [HttpHandler("GET", "/users/:id")]
    public async Task GetUser(Request request, Response response)
    {
        var userId = request.Params.id;
        var user = GetUserById(userId);
        
        if (user == null)
        {
            await response.JsonResponse(404, new { error = "User not found" });
            return;
        }
        
        await response.JsonResponse(200, user);
    }

    [HttpHandler("POST", "/users")]
    public async Task CreateUser(Request request, Response response)
    {
        var userData = request.Json<CreateUserRequest>();
        
        // 参数验证
        if (!Validation.Valid(userData, out string reason))
        {
            await response.JsonResponse(400, new { error = reason });
            return;
        }
        
        var newUser = CreateUser(userData);
        await response.JsonResponse(201, newUser);
    }
}

// 注册控制器
Server.RegisterController<UserController>();

直接注册处理器

csharp
// 注册单个处理器
Server.RegisterHandler("GET", "/hello", async (request, response) =>
{
    await response.StringResponse(200, "Hello World!");
});

// 链式注册
Server.GetServer(8080)
    .Register("GET", "/ping", async (req, res) =>
    {
        await res.JsonResponse(200, new { message = "pong" });
    })
    .Register("POST", "/echo", async (req, res) =>
    {
        var data = req.Json<dynamic>();
        await res.JsonResponse(200, data);
    })
    .UseCors();

请求参数处理

csharp
[HttpHandler("GET", "/search")]
public async Task Search(Request request, Response response)
{
    // 查询参数
    var keyword = request.Query.keyword;
    var page = request.Query.page ?? "1";
    
    // 请求头
    var userAgent = request.Header["user-agent"];
    var authorization = request.Header.authorization;
    
    var results = SearchService.Search(keyword, int.Parse(page));
    await response.JsonResponse(200, results);
}

[HttpHandler("POST", "/upload")]
public async Task Upload(Request request, Response response)
{
    // 表单数据
    var title = request.Form.title;
    var description = request.Form.description;
    
    // 请求体
    var body = request.BodyString;
    
    await response.JsonResponse(200, new { success = true });
}

参数验证示例

csharp
public class CreateUserRequest
{
    [Required(Message = "用户名不能为空")]
    public string Username { get; set; }

    [Required(Message = "邮箱地址不能为空")]
    public string Email { get; set; }

    public string Phone { get; set; } // 可选字段
}

[HttpHandler("POST", "/users")]
public async Task CreateUser(Request request, Response response)
{
    var userData = request.Json<CreateUserRequest>();
    
    if (!Validation.Valid(userData, out string reason))
    {
        await response.JsonResponse(400, new { 
            success = false, 
            message = reason 
        });
        return;
    }
    
    // 处理有效数据
    var user = UserService.Create(userData);
    await response.JsonResponse(201, new { 
        success = true, 
        data = user 
    });
}

中间件示例

csharp
// 身份验证中间件
server.Use(async (context, next) =>
{
    var path = context.Request.Path.Value;
    
    // 跳过公开路径
    if (path.StartsWith("/public"))
    {
        await next();
        return;
    }
    
    var token = context.Request.Headers["Authorization"].FirstOrDefault();
    if (string.IsNullOrEmpty(token))
    {
        context.Response.StatusCode = 401;
        await context.Response.WriteAsync("Unauthorized");
        return;
    }
    
    // 验证 token
    if (ValidateToken(token))
    {
        await next();
    }
    else
    {
        context.Response.StatusCode = 401;
        await context.Response.WriteAsync("Invalid token");
    }
});

// 请求日志中间件
server.Use(async (context, next) =>
{
    var stopwatch = Stopwatch.StartNew();
    await next();
    stopwatch.Stop();
    
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} " +
                     $"- {context.Response.StatusCode} ({stopwatch.ElapsedMilliseconds}ms)");
});

错误处理

csharp
[HttpHandler("GET", "/users/:id")]
public async Task GetUser(Request request, Response response)
{
    try
    {
        var userId = int.Parse(request.Params.id);
        var user = await UserService.GetByIdAsync(userId);
        
        if (user == null)
        {
            await response.JsonResponse(404, new { 
                error = "User not found",
                code = "USER_NOT_FOUND"
            });
            return;
        }
        
        await response.JsonResponse(200, user);
    }
    catch (FormatException)
    {
        await response.JsonResponse(400, new { 
            error = "Invalid user ID format",
            code = "INVALID_FORMAT"
        });
    }
    catch (Exception ex)
    {
        Logger.Error($"Error in GetUser: {ex}");
        await response.JsonResponse(500, new { 
            error = "Internal server error",
            code = "INTERNAL_ERROR"
        });
    }
}

文件上传处理

csharp
[HttpHandler("POST", "/files/upload")]
public async Task UploadFile(Request request, Response response)
{
    if (request.RawRequest.HasFormContentType && 
        request.RawRequest.Form.Files.Count > 0)
    {
        var file = request.RawRequest.Form.Files[0];
        var fileName = $"{Guid.NewGuid()}_{file.FileName}";
        var filePath = Path.Combine("uploads", fileName);
        
        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
        
        await response.JsonResponse(200, new { 
            success = true,
            fileName = fileName,
            size = file.Length
        });
    }
    else
    {
        await response.JsonResponse(400, new { 
            error = "No file uploaded" 
        });
    }
}

配置选项

调试模式

csharp
var server = Server.GetServer(8080);
server.DebugMode = true; // 显示详细错误信息

自定义错误处理

csharp
server.Use(async (context, next) =>
{
    try
    {
        await next();
    }
    catch (BusinessException ex)
    {
        context.Response.StatusCode = 400;
        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { 
            error = ex.Message,
            code = ex.Code
        }));
    }
    catch (Exception ex)
    {
        Logger.Error(ex.ToString());
        context.Response.StatusCode = 500;
        await context.Response.WriteAsync("Internal server error");
    }
});

依赖项

  • Microsoft.AspNetCore.Hosting: ASP.NET Core 宿主
  • Microsoft.AspNetCore.Server.Kestrel: Kestrel 服务器
  • Newtonsoft.Json: JSON 序列化
  • Ccxc.Core.Utils: 核心工具包

Released under the MIT License. Powered by VitePress.