创建HttpService
定义
命名空间:TouchSocket.Http
程序集:TouchSocket.Http.dll
一、说明
HttpService是能够提供Http相关服务的基础类型。
二、产品特点
- 支持HTTPS。
- 多种数据接收模式
- 多地址监听(可以一次性监听多个IP及端口)
三、产品应用场景
- HTTP基础使用场景:可跨平台、跨语言使用。
四、服务器架构
服务器在收到新客户端连接时,会创建一个HttpSessionClient
的派生类实例,与远程HttpClient
对应,后续的数据通信均由此实例负责。
五、支持插件接口
声明自定义实例类,然后实现IHttpPlugin
接口,即可实现下列事务的触发。或者继承自PluginBase
类,重写相应方法即可。
插件方法 | 功能 |
---|---|
IHttpPlugin | 当收到所有Http请求时。 |
六、创建HttpService
HttpService
的创建,基本和TcpService
一致,也可以通过继承实现,下列仅演示最简单实现。
HttpService
的相关事务,会通过插件触发。
var service = new HttpService();
await service.SetupAsync(new TouchSocketConfig()//加载配置
.SetListenIPHosts(7789)
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
//此处添加插件逻辑,插件可以使用PluginBase类实现IHttpPlugin接口完成。
//这里使用委托直接完成
a.Add(typeof(IHttpPlugin), async (HttpContextEventArgs e) =>
{
var request = e.Context.Request;//http请求体
var response = e.Context.Response;//http响应体
//判断url
if (request.UrlEquals("/say"))
{
await response
.SetStatus(200, "success")
.SetContent("hello")
.AnswerAsync();
return;
}
//如果上述url没有处理,则转到下一插件处理
await e.InvokeNext();
});
//default插件应该最后添加,其作用是
//1、为找不到的路由返回404
//2、处理header为Option的探视跨域请求。
a.UseDefaultHttpServicePlugin();
}));
await service.StartAsync();
提示
DefaultHttpServicePlugin
插件最好添加在插件中,如果没有添加的话,最好自己做好缺省路由配置。
七、获取请求
每个HttpClient
连接建立时,系统除了会创建一个HttpSessionClient
与之对应之外,还会创建一个HttpContext
实例与之对应。
所以,对于一个连接而言,后续的所有Http
交互,都会反复投递同一个HttpContext
实例。
所以我们可以通过其Request
与Response
属性获取到本次Http的请求和即将响应的响应体。
var request = e.Context.Request;//http请求体
var response = e.Context.Response;//http响应体
7.1 获取Query参数
string value = e.Context.Request.Query["key"];
7.2 获取Header参 数
string value = e.Context.Request.Headers["key"];
亦或者
string value = e.Context.Request.Headers[HttpHeaders.Cookie];
7.3 获取Form参数
string value = e.Context.Request.Forms["key"];
7.4 获取字符串Body内容
string bodyString = await e.Context.Request.GetBodyAsync();
7.5 获取小体量字节Body内容
ReadOnlyMemory<byte> content = await e.Context.Request.GetContentAsync();
7.6 持续读取Body内容
当数据太大时,可持续读取
while (true)
{
var buffer = new byte[1024 * 64];
using (var blockResult = await e.Context.Request.ReadAsync())
{
//这里可以一直处理读到的数据。
blockResult.Memory.CopyTo(buffer);
if (blockResult.IsCompleted)
{
//结束
break;
}
}
}
7.7 获取Body持续写入Stream中
当数据太大时,可持续读取数据直接到流容器中。
using (var stream = new MemoryStream())
{
//
await e.Context.Request.ReadCopyToAsync(stream);
}