Files
TouchSocket/handbook/docs/httpservice.mdx
若汝棋茗 6ec64f93b6 更新demo
2024-01-20 20:41:59 +08:00

297 lines
8.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: httpservice
title: 创建HttpService
---
### 定义
命名空间TouchSocket.Http <br/>
程序集:[TouchSocket.Http.dll](https://www.nuget.org/packages/TouchSocket.Http)
## 一、说明
**HttpService**是能够提供Http相关服务的基础类型。
## 二、产品特点
- 支持HTTPS。
- **多种数据接收模式**
- **多地址监听**可以一次性监听多个IP及端口
## 三、产品应用场景
- HTTP基础使用场景可跨平台、跨语言使用。
## 四、服务器架构
服务器在收到新客户端连接时会创建一个HttpSocketClient的派生类实例与远程HttpClient对应后续的数据通信均由此实例负责。
<img src={require('@site/static/img/docs/createhttpservice-1.png').default} width="500" />
## 五、支持插件接口
声明自定义实例类,然后实现**IHttpPlugin**接口,即可实现下列事务的触发。或者继承自**HttpPluginBase**类,重写相应方法即可。
| 插件方法| 功能 |
| --- | --- |
| IHttpPlugin | 当收到所有Http请求时。|
## 六、使用HttpService
HttpService的创建基本和TcpService一致也可以通过继承实现下列仅演示最简单实现。
HttpService的相关事务会通过**插件**触发。
### 6.1 创建HttpService
```csharp showLineNumbers
var service = new HttpService();
service.Setup(new TouchSocketConfig()//加载配置
.SetListenIPHosts(7789)
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
//以下即是插件
a.Add<MyHttpPlug1>();
a.Add<MyHttpPlug2>();
a.Add<MyHttpPlug3>();
a.Add<MyHttpPlug4>();
//default插件应该最后添加其作用是
//1、为找不到的路由返回404
//2、处理header为Option的探视跨域请求。
a.UseDefaultHttpServicePlugin();
}));
service.Start();
```
:::tip 提示
DefaultHttpServicePlugin插件最好添加在插件中如果没有添加的话最好自己做好缺省路由和跨域配置。
:::
### 6.2 使用插件处理请求参数
#### 6.2.1 Query参数
```csharp showLineNumbers
string value = e.Context.Request.Query["key"];
```
#### 6.2.2 Header参数
```csharp showLineNumbers
string value = e.Context.Request.Headers["key"];
```
亦或者
```csharp showLineNumbers
string value = e.Context.Request.Headers[HttpHeaders.Cookie];
```
#### 6.2.3 Form参数
```csharp showLineNumbers
string value = e.Context.Request.Forms["key"];
```
### 6.3 使用插件处理请求
#### 6.3.1 Get请求
```csharp showLineNumbers
public class MyHttpPlug1 : PluginBase, IHttpPlugin<IHttpSocketClient>
{
public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.IsGet())
{
if (e.Context.Request.UrlEquals("/success"))
{
//直接响应文字
e.Context.Response.FromText("Success").Answer();//直接回应
Console.WriteLine("处理完毕");
return;
}
}
//无法处理,调用下一个插件
await e.InvokeNext();
}
}
```
#### 6.3.2 Get文件请求
```csharp showLineNumbers
public class MyHttpPlug2 : PluginBase, IHttpPlugin<IHttpSocketClient>
{
public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.IsGet())
{
if (e.Context.Request.UrlEquals("/file"))
{
try
{
//直接回应文件。
e.Context.Response
.SetStatus()//必须要有状态
.FromFile(@"D:\System\Windows.iso", e.Context.Request);
}
catch (Exception ex)
{
e.Context.Response.SetStatus(403)
.FromText(ex.Message)
.Answer();
}
return;
}
}
await e.InvokeNext();
}
}
```
#### 6.3.3 Get页面请求
```csharp showLineNumbers
public class MyHttpPlug3 : PluginBase, IHttpPlugin<IHttpSocketClient>
{
public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.IsGet())
{
if (e.Context.Request.UrlEquals("/html"))
{
//回应html
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("<!DOCTYPE html>");
stringBuilder.AppendLine("<html>");
stringBuilder.AppendLine("<head>");
stringBuilder.AppendLine("<meta charset=\"utf-8\"/>");
stringBuilder.AppendLine("<title>TouchSocket</title>");
stringBuilder.AppendLine("</head>");
stringBuilder.AppendLine("<body>");
stringBuilder.AppendLine("<div id=\"kuang\" style=\"width: 50%;height: 85%;left: 25%;top:15%;position: absolute;\">");
stringBuilder.AppendLine("<a id=\"MM\" style=\"font-size: 30px;font-family: 微软雅黑;width: 100%;\">王二麻子</a>");
stringBuilder.AppendLine("<input type=\"text\" id=\"NN\" value=\"\" style=\"font-size: 30px;width:100%;position: relative;top: 30px;\"/>");
stringBuilder.AppendLine("<input type=\"button\" id=\"XX\" value=\"我好\" style=\"font-size: 30px;width: 100%;position: relative;top: 60px;\" onclick=\"javascript:jump()\" />");
stringBuilder.AppendLine("</div>");
stringBuilder.AppendLine("</body>");
stringBuilder.AppendLine("</html>");
e.Context.Response
.SetStatus()//必须要有状态
.SetContentTypeByExtension(".html")
.SetContent(stringBuilder.ToString());
e.Context.Response.Answer();
return;
}
}
await e.InvokeNext();
}
}
```
#### 6.3.4 Post文件请求
```csharp showLineNumbers
public class MyHttpPlug4 : PluginBase, IHttpPlugin<IHttpSocketClient>
{
public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
{
if (e.Context.Request.IsPost())
{
if (e.Context.Request.UrlEquals("/uploadfile"))
{
try
{
if (e.Context.Request.TryGetContent(out var bodys))//一次性获取请求体
{
return;
}
while (true)//当数据太大时,可持续读取
{
var buffer = new byte[1024 * 64];
var r = e.Context.Request.Read(buffer, 0, buffer.Length);
if (r == 0)
{
return;
}
//这里可以一直处理读到的数据。
}
//下面逻辑是接收小文件。
if (e.Context.Request.ContentLength > 1024 * 1024 * 100)//全部数据体超过100Mb则直接拒绝接收。
{
e.Context.Response
.SetStatus(403, "数据过大")
.Answer();
return;
}
//此操作会先接收全部数据,然后再分割数据。
//所以上传文件不宜过大,不然会内存溢出。
var multifileCollection = e.Context.Request.GetMultifileCollection();
foreach (var item in multifileCollection)
{
var stringBuilder = new StringBuilder();
stringBuilder.Append($"文件名={item.FileName}\t");
stringBuilder.Append($"数据长度={item.Length}");
client.Logger.Info(stringBuilder.ToString());
}
e.Context.Response
.SetStatus()
.FromText("Ok")
.Answer();
}
catch (Exception ex)
{
client.Logger.Exception(ex);
}
}
}
await e.InvokeNext();
}
}
```
:::tip 提示
该操作支持大型文件,也支持断点续传、支持迅雷加速等。
:::
## 七、创建加密Ssl的HttpsService
Https服务器和http服务器几乎一样只不过增加了一个Ssl的配置。
```csharp showLineNumbers
.SetServiceSslOption(new ServiceSslOption()
{
Certificate = new X509Certificate2("Socket.pfx", "Socket"),
SslProtocols = SslProtocols.Tls12
})
```
[本文示例Demo](https://gitee.com/RRQM_Home/TouchSocket/tree/master/examples/Http)