HttpServer是一个轻量级Web服务器,用于在嵌入式设备以及客户端环境中提供简单Web服务。
HttpServer支持路由映射到匿名委托、WebApi接口、静态文件,以及具有多个接口的控制器类。从简单到复杂,控制权交给开发者。
源码: https://github.com/NewLifeX/X/blob/master/NewLife.Core/Http/HttpServer.cs
Nuget:NewLife.Core
Get Started
准备好vs2022,新建.NET6.0控制台项目
从nuget引用 NewLife.Core 包,找到包后点击安装,将会安装最新版
打开源码文件 Program.cs ,输入以下例程,该例程将会监听8080端口提供Web服务,并打开所有日志,映射了4个不同的路由。
using NewLife.Http; using NewLife.Log; using NewLife.Remoting; XTrace.UseConsole(); var server = new HttpServer { Port = 8080, Log = XTrace.Log, SessionLog = XTrace.Log }; server.Map("/", () => "<h1>Hello NewLife!</h1></br> " + DateTime.Now.ToFullString() + "</br><img src=\"logos/leaf.png\" />"); server.Map("/user", (String act, Int32 uid) => new { code = 0, data = $"User.{act}({uid}) success!" }); server.MapStaticFiles("/logos", "images/"); server.MapController<ApiController>("/api"); server.Start(); Console.ReadLine();
点击绿色三角箭头启动调试,或者按F5快捷键启动
vs2022将会自动编译源码并启动应用,弹出控制台窗口
控制台日志显示,网络应用程序已经开始监听8080端口,分别在IPv4和IPv6上同时监听。
通过浏览器访问 http://localhost:8080/ ,可以得到以下页面。
这是第一个路由映射的HTML页面。(图片文件没有放到相应目录下,所以没显示)
普通Html
HttpServer支持路由映射到一个返回html字符串的匿名方法
server.Map("/", () => "<h1>Hello NewLife!</h1></br> " + DateTime.Now.ToFullString() + "</br><img src=\"logos/leaf.png\" />");
路由路径为/,也就是根目录。这个匿名函数很简单,没有参数(也可以有参数),返回字符串。服务端就认为返回的是html文本。
如果返回类型是Byte[]或者Stream等二进制数据,则使用 application/octet-stream 类型。
如果处理函数内部抛出异常,则服务端将向浏览器返回500错误。
Api接口
HttpServer支持路由到WebApi接口,支持从url截取参数,支持POST自定义Json格式参数。
server.Map("/user", (String act, Int32 uid) => new { code = 0, data = $"User.{act}({uid}) success!" });
访问地址 http://localhost:8080/user?act=edit&uid=1234 得到
路由路径是/user。该接口返回一个对象,HttpServer将进行json序列化后返回。
上面WebApi接口的参数来自于Url字符串,实际上也可以来自于表单提交,或者json格式的数据Post。
静态文件
HttpServer支持路由到静态文件,可通过http访问指定目录下所有静态文件。
server.MapStaticFiles("/logos", "images/");
路由路径是/logos,指向当前目录的images子目录下的文件。
例如前面html中访问 /logos/leaf.png ,实际上指向 images/leaf.png ,需要在 images 子目录下放置 leaf.png 文件。从 http://x.newlifex.com/leaf.png 下载图片,放到images目录下,当然也可以用自己的图片。选中leaf.png文件,下方属性窗的复制到输出目录,选择“如果较新则复制”。
按F5再次跑起来项目,访问 http://localhost:8080/ 。
从日志可以看到,请求根目录/后,html里面img再次请求 /logos/leaf.png 图片。
HttpServer仅支持常用文件类型的MineType。
注意:静态文件处理器实现比较简单,可以下载dll和config等任意文件,但路径上做了限制,禁止跳出本地目录。
接口控制器
HttpServer支持映射到控制器类,内部所有公开实例方法作为下级路由。
server.MapController<ApiController>("/api");
路由路径/api映射控制器ApiController下所有公开接口。该类下共有 All/Info/Info2 几个接口。
访问路径 http://localhost:8080/api/info 可以看到:
本质上就是映射 /api/info 到 ApiController 内部的 Info 方法。
接口参数支持来自于Url与表单提交,或者Json提交。
专用处理器IHttpHandler
HttpServer 对上述功能的支持,本质上就是把路由映射到 IHttpHandler 实现。因为完全可以通过自定义 IHttpHandler 实现来达到完全自定义Http处理的效果。
IHttpHandler 接口只有一个成员方法 ProcessRequest,传入 IHttpContext 上下文。上下文中有Request请求和Response响应。
namespace NewLife.Http { // // 摘要: // Http处理器 public interface IHttpHandler { // // 摘要: // 处理请求 // // 参数: // context: void ProcessRequest(IHttpContext context); } }
编写一下例程:
class MyHttpHandler : IHttpHandler { public void ProcessRequest(IHttpContext context) { var name = context.Parameters["name"]; var html = $"<h2>你好,<span color=\"red\">{name}</span></h2>"; context.Response.SetResult(html); } }
context.Parameters中有解析好的Url参数,Response.SetResult设置响应数据和MineType类型。
然后在Programe.cs中增加映射
server.Map("/my", new MyHttpHandler());
按F5启动,访问地址 http://localhost:8080/my?name=Stone 。
文件上传
HttpServer 支持多文件上传,在 context.Request.Files 中对文件进行访问。不建议上传大文件,因为 HttpServer 是轻量级服务端,在接收完整个请求头之前,会在内存完成拼接。如果上传一个2G文件,实际占用内存也会增加2G。
访问上传文件的示例如下:
class MyHttpHandler : IHttpHandler { public void ProcessRequest(IHttpContext context) { var name = context.Parameters["name"]; var html = $"<h2>你好,<span color=\"red\">{name}</span></h2>"; var files = context.Request.Files; if (files != null && files.Length > 0) { foreach (var file in files) { file.SaveToFile(); html += $"<br />文件:{file.FileName} 大小:{file.Length} 类型:{file.ContentType}"; } } context.Response.SetResult(html); } }
遍历 context.Request.Files 集合,然后 file.SaveToFile() 保存文件到本地磁盘。
树莓派跑起来
部署到树莓派(这里不深入如何安装.NET6.0)
然后 curl 跑起来