点击或拖拽改变大小

HttpServer 类

一个支持完全自定义的Http服务器,支持返回任意的数据信息,方便调试信息,详细的案例请查看API文档信息
A Http server that supports fully customized, supports returning arbitrary data information, which is convenient for debugging information. For detailed cases, please refer to the API documentation information
继承层次
SystemObject
  HslCommunication.EnthernetHttpServer
    HslCommunication.Robot.ABBABBWebApiServer

命名空间:  HslCommunication.Enthernet
程序集:  HslCommunication (在 HslCommunication.dll 中) 版本:11.8.2.0 (11.8.2.0)
语法
public class HttpServer

HttpServer 类型公开以下成员。

构造函数
  名称说明
公共方法HttpServer
实例化一个默认的对象,当前的运行,需要使用管理员的模式运行
Instantiate a default object, the current operation, you need to use the administrator mode to run
Top
属性
  名称说明
公共属性ApiCalledAction
获取或设置当前接口调用信息处理的委托,可以用于对接口调用的二次分析,在接口调用完成的时候,将触发本委托
Obtain or set the delegate for the current interface call information processing, which can be used for secondary analysis of the interface call, and the delegate will be triggered when the interface call is completed
公共属性DealWithHttpListenerRequest
额外的处理请求信息的委托定义,将可以自定义处理一些特殊的请求头数据,例如一些账户相关的其他属性,语言属性等等。
Additional delegate definitions for processing request information will be able to customize some special request header data, such as some other account-related attributes, language attributes, and so on.
公共属性HandleFileUpload
获取或设置当前的自定义处理文件上传的信息,自动解析好文件的基本信息
Obtain or set the current custom processing file upload information, and automatically parse the basic information of the file
公共属性HandleRequestFunc
获取或设置当前的自定义的处理信息,如果不想继承实现方法,可以使用本属性来关联你自定义的方法。
Get or set the current custom processing information. If you don't want to inherit the implementation method, you can use this attribute to associate your custom method.
公共属性IsCrossDomain
获取或设置是否支持跨域操作
Get or set whether to support cross-domain operations
公共属性代码示例LogNet
组件的日志工具,支持日志记录,只要实例化后,当前网络的基本信息,就以DEBUG等级进行输出
The component's logging tool supports logging. As long as the instantiation of the basic network information, the output will be output at DEBUG
公共属性LogStatistics
获取当前的日志统计信息,可以获取到每个API的每天的调度次数信息,缓存60天数据,如果需要存储本地,需要调用SaveToFile(String)方法。
Get the current log statistics, you can get the daily scheduling times information of each API, and cache 60-day data. If you need to store it locally, you need to call the SaveToFile(String) method.
公共属性Port
获取当前的端口号信息
Get current port number information
公共属性ServerEncoding
获取或设置当前服务器的编码信息,默认为UTF8编码
Get or set the encoding information of the current server, the default is UTF8 encoding
Top
方法
  名称说明
公共方法Close
关闭服务器
Shut down the server
公共方法Equals (继承自 Object。)
受保护的方法Finalize (继承自 Object。)
公共方法GetAllRpcApiInfo
获取当前所有注册的RPC接口信息,将返回一个数据列表。
Get all currently registered RPC interface information, and a data list will be returned.
公共方法GetHashCode (继承自 Object。)
公共方法静态成员GetMethodName
根据完整的地址获取当前的url地址信息
公共方法GetType (继承自 Object。)
公共方法静态成员HandleObjectMethod(HttpListenerRequest, String, String, MqttRpcApiInfo, ActionHttpListenerRequest, ISessionContext)
使用指定的对象来返回网络的API接口,前提是传入的数据为json参数,返回的数据为json数据,详细参照说明
Use the specified object to return the API interface of the network, provided that the incoming data is json parameters and the returned data is json data, please refer to the description for details
公共方法静态成员HandleObjectMethod(HttpListenerRequest, String, String, Object, ActionHttpListenerRequest, ISessionContext)
使用指定的对象来返回网络的API接口,前提是传入的数据为json参数,返回的数据为json数据,详细参照说明
Use the specified object to return the API interface of the network, provided that the incoming data is json parameters and the returned data is json data, please refer to the description for details
受保护的方法HandleRequest
根据客户端的请求进行处理的核心方法,可以返回自定义的数据内容,只需要集成重写即可。
The core method of processing according to the client's request can return custom data content, and only needs to be integrated and rewritten.
受保护的方法MemberwiseClone (继承自 Object。)
公共方法RegisterHttpRpcApi(Object)
注册一个RPC的服务接口,可以指定当前的控制器名称,以及提供RPC服务的原始对象
Register an RPC service interface, you can specify the current controller name, and the original object that provides the RPC service
公共方法RegisterHttpRpcApi(String, Object)
注册一个RPC的服务接口,可以指定当前的控制器名称,以及提供RPC服务的原始对象
Register an RPC service interface, you can specify the current controller name, and the original object that provides the RPC service
公共方法SetLoginAccessControl
设置登录的账户信息,如果需要自己控制,可以自己实现委托HandleRequestFunc
Set the login account information, if you need to control by yourself, you can implement the delegation by yourselfHandleRequestFunc
公共方法Start
启动服务器,正常调用该方法时,应该使用try...catch...来捕获错误信息
Start the server and use try...catch... to capture the error message when calling this method normally
公共方法ToString (重写 ObjectToString.)
Top
扩展方法
  名称说明
公共扩展器方法ToJsonString
获取当前对象的JSON格式表示的字符串。
Gets the string represented by the JSON format of the current object.
(由 HslExtension 定义。)
Top
备注
使用RPC接口注册的方式,可以更加便捷快速的实现webapi接口创建及设计,自带接口列表浏览查看,注释查看,签名查看,甚至调用次数及耗时查看。
Using the RPC interface registration method, you can more conveniently and quickly realize the creation and design of webapi interfaces, browse and view the built-in interface list, view comments, view signatures, and even view the number of calls and time-consuming.
示例
我们先来看看一个最简单的例子,如何进行实例化的操作。
基本的实例化
private HttpServer httpServer;                                                     // 当前的Web服务器,支持web api来通信的方式

private void Start( )
{
    // 启动web的服务器
    try
    {
        this.httpServer = new HttpServer( );
        this.httpServer.Start( 8000 );
    }
    catch (Exception ex)
    {
        Console.WriteLine( "Web服务器加载失败!" + ex.Message );
    }
}

// 调用start方法之后,我们打开浏览器,输入 http://127.0.0.1:8000 就可以看到如下的文本 "This is HslWebServer, Thank you for use!"
// After calling the start method, we open the browser and enter http://127.0.0.1:8000 to see the following text: "This is HslWebServer, Thank you for use!"
通常来说,基本的实例化,返回固定的数据并不能满足我们的需求,我们需要返回自定义的数据,有一个委托,我们需要自己指定方法.
自定义返回
private HttpServer httpServer;                                                     // 当前的Web服务器,支持web api来通信的方式

private void Start( )
{
    // 启动web的服务器
    try
    {
        this.httpServer = new HttpServer( );
        this.httpServer.HandleRequestFunc = HandleRequest;
        this.httpServer.Start( 8000 );
    }
    catch (Exception ex)
    {
        Console.WriteLine( "Web服务器加载失败!" + ex.Message );
    }
}

private string HandleRequest( HttpListenerRequest request, HttpListenerResponse response, string data )
{
    if (request.HttpMethod == "GET")
    {
        return "This is Get Method";
    }
    else if (request.HttpMethod == "POST")
    {
        return "This is Post Method";
    }
    else
    {
        return string.Empty;
    }
}
我们实际的需求可能会更加的复杂,不同的网址会返回不同的数据,所以接下来我们需要对网址信息进行判断。
区分网址
private string HandleRequest( HttpListenerRequest request, HttpListenerResponse response, string data )
{
    if (request.HttpMethod == "GET")
    {
        if (request.RawUrl == "/GetA")
        {
            return "This is GetA Method";
        }
        else if (request.RawUrl == "/GetB")
        {
            return "This is GetB Method";
        }
        else
        {
            return "This is Notsupported Method";
        }
    }
    else if (request.HttpMethod == "POST")
    {
        if (request.RawUrl == "/PostA")
        {
            Console.WriteLine( data );   // data 就是post上来的数据信息
            return "OK";
        }
        return "This is Post Method";
    }
    else
    {
        return string.Empty;
    }
}
如果我们想增加安全性的验证功能,比如我们的api接口需要增加用户名和密码的功能,那么我们也可以实现
安全实现
private string HandleRequest( HttpListenerRequest request, HttpListenerResponse response, string data )
{
    // 下面的对授权验证增加用户名和密码的操作,当使用浏览器登录的时候,会自动弹出输入用户名及密码的窗口
    // The following operation for adding a username and password for authorization verification will automatically pop up a window for 
    // entering the username and password when logging in with a browser.
    string[] values = request.Headers.GetValues( "Authorization" );
    if (values == null || values.Length < 1 || string.IsNullOrEmpty( values[0] ))
    {
        response.StatusCode = 401;
        response.AddHeader( "WWW-Authenticate", "Basic realm=\"Secure Area\"" );
        return "";
    }

    string base64String = values[0].Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries )[1];
    string accountString = Encoding.UTF8.GetString( Convert.FromBase64String( base64String ) );
    string[] account = accountString.Split( new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries );
    if (account.Length < 2)
    {
        response.StatusCode = 401;
        response.AddHeader( "WWW-Authenticate", "Basic realm=\"Secure Area\"" );
        return "";
    }

    // 此处假定用户名和密码限定了 admin 123456
    if (!(account[0] == "admin" && account[1] == "123456"))
    {
        response.StatusCode = 401;
        response.AddHeader( "WWW-Authenticate", "Basic realm=\"Secure Area\"" );
        return "";
    }

    if (request.HttpMethod == "GET")
    {
        if (request.RawUrl == "/GetA")
        {
            return "This is GetA Method";
        }
        else if (request.RawUrl == "/GetB")
        {
            return "This is GetB Method";
        }
        else
        {
            return "This is Notsupported Method";
        }
    }
    else if (request.HttpMethod == "POST")
    {
        if (request.RawUrl == "/PostA")
        {
            Console.WriteLine( data );   // data 就是post上来的数据信息
            return "OK";
        }
        return "This is Post Method";
    }
    else
    {
        return string.Empty;
    }
}
当然了,如果我们想反回一个完整的html网页,也是可以实现的,甚至添加一些js的脚本,下面的例子就简单的说明了如何操作
返回html
private string HandleRequest( HttpListenerRequest request, HttpListenerResponse response, string data )
{
    if (request.HttpMethod == "GET")
    {
        if (request.RawUrl == "/GetA") // 当浏览器浏览一个网页的时候,输入 http://127.0.0.1:6000/GetA 会显示网络内容
        {
            response.AddHeader( "Content-type", $"Content-Type: text/html; charset=utf-8" );
            return "<html><head><title>HslWebServer</title></head><body><p style=\"color: red\">这是一个测试的消息内容</p></body></html>";
        }
        else
        {
            return "This is Notsupported Method";
        }
    }
    else if (request.HttpMethod == "POST")
    {
        return "This is Post Method";
    }
    else
    {
        return string.Empty;
    }
}
如果需要实现跨域的操作,可以将属性IsCrossDomain 设置为True

上述的代码编写接口还是很费劲的,接口的方法还不能在服务器复用,所以参考下面的代码来编写接口会更加的高级和便捷。
高级RPC注册
private HttpServer httpServer;                                                     // 当前的Web服务器,支持web api来通信的方式

private void Start( )
{
    // 启动web的服务器
    try
    {
        this.httpServer = new HttpServer( );
        this.httpServer.RegisterHttpRpcApi( this );       // 将当前类的方法接口(带HslMqttApi特性)注册为RPC接口

        // 如果需要控制账户登录的情况,如果不需要,直接注释下面的三行代码
        this.httpServer.SetLoginAccessControl( 
            new HslCommunication.MQTT.MqttCredential[] {
                new HslCommunication.MQTT.MqttCredential("admin", "123456")} );


        // 启动服务
        this.httpServer.Start( 8000 );
    }
    catch (Exception ex)
    {
        Console.WriteLine( "Web服务器加载失败!" + ex.Message );
    }
}

[HslCommunication.Reflection.HslMqttApi(Description = "这是求加法结果的RPC接口", HttpMethod = "GET")]
public int Add( int a, int b )
{
    return a + b;
}

/// <summary>
/// 一个更高级的RPC接口,用来校验用户名,密码,并且返回是否校验成功的结果
/// </summary>
/// <param name="name">用户名</param>
/// <param name="password">密码</param>
/// <returns>是否校验成功的结果</returns>
[HslCommunication.Reflection.HslMqttApi( Description = "校验用户名,密码,并且返回是否校验成功的结果,name:用户名 password:密码", HttpMethod = "GET" )]
public HslCommunication.OperateResult<string> CheckAccount( string name, string password )
{
    if (name == null) return new HslCommunication.OperateResult<string>( "user name can not be null" );
    if (password == null) return new HslCommunication.OperateResult<string>( "pwd can not be null" );
    if (name == "admin" && password == "123456") return HslCommunication.OperateResult.CreateSuccessResult( "" );
    return new HslCommunication.OperateResult<string>( "account or pwd wrong" );
}

public class UserData
{
    public string Name { get; set; } = "Name";
    public string A { get; set; } = "A";
    public string B { get; set; } = "B";
}

/// <summary>
/// 甚至参数可以定义为自定义类型,不过需要确保可以从json转换,自定义类型的接口使用 POST 方式,更好的传参
/// 本接口示例就是回传用户的名字
/// </summary>
/// <param name="userData">用户对象</param>
/// <returns>返回用户的名称</returns>
[HslCommunication.Reflection.HslMqttApi( Description = "回传用户的名字,参数为 UserData 对象", HttpMethod = "POST" )]
public HslCommunication.OperateResult<string> GetName( UserData userData )
{
    return HslCommunication.OperateResult.CreateSuccessResult( userData.Name );
}


// 下面演示带安全策略的接口,我有一个接口是需要面向指定用户的,而不是所有用户都可以调用的
// 那么需要参考启动的时候进行账户检查,这里演示,只能 admin 账户可以调用下面的方法

/// <summary>
/// 这是一个计算数据的RPC接口
/// </summary>
/// <param name="sessionContext">会话内容</param>
/// <param name="a">参数a</param>
/// <param name="b">参数b</param>
/// <returns>返回计算结果</returns>
[HslCommunication.Reflection.HslMqttApi( Description = "这是一个计算数据的RPC接口,只能admin账户调用,a:参数a b:参数b", HttpMethod = "GET" )]
public HslCommunication.OperateResult<int> Calculate( HslCommunication.Core.ISessionContext sessionContext, int a, int b )
{
    if (sessionContext.UserName == "admin") return HslCommunication.OperateResult.CreateSuccessResult( a * b );
    return new HslCommunication.OperateResult<int>( "Not supported" );
}
参见