RaUI/Source/MyDb/RyWeb/HttpServer.cs
鑫Intel 00c9dec061 ### 2022-03-01更新
------
#### MyDbV4    V3.0.2203.0101
- *.[新增]新增IsInTime和IsInDay扩展函数。
- *.[改进]完善部分注释,更加易懂。
- *.[改进]HttpServer类新增默认对postdata内容进行解析。
- *.[修复]修复PinYin类对《鑫》字转换错误的BUG。

#### MyDb_MySQLV4    V3.0.2203.0101
- *.[改进]MySQL的连接字符串自动追加Allow User Variables=True;
2022-03-01 17:01:48 +08:00

257 lines
7.7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using ryCommon;
namespace RyWeb
{
/// <summary>
/// Http服务器类
/// </summary>
public class HttpServer
{
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void HttpRequestHandler(object sender, HttpRequest e);
/// <summary>
/// 当收到Get事件时激发
/// </summary>
[Description("当收到Get事件时激发")]
public event HttpRequestHandler OnHandleGETRequest;
/// <summary>
/// 当收到Post事件时激发
/// </summary>
[Description("当收到Post事件时激发")]
public event HttpRequestHandler OnHandlePOSTRequest;
private HttpListener listener;
private Thread httpThread;
private volatile bool stopped = false;
/// <summary>
/// 监听的主机,默认是localhost
/// </summary>
public string ListenerHost { get; set; } = "localhost";
private int port = 19955;
/// <summary>
/// 最后一次错误信息
/// </summary>
public string ErrorMessage { get;internal set; } = "";
/// <summary>
/// 在此端口建立Http服务类
/// </summary>
/// <param name="port">端口号</param>
public HttpServer(int port)
{
isrunning = false;
stopped = false;
try
{
listener = new HttpListener();
this.port= port;
listener.Prefixes.Add("http://"+ ListenerHost + ":" + port + "/");
//listener.Prefixes.Add(HTTPS_PREFIX + HTTPS_PORT + "/");
listener.Start();
httpThread = new Thread(new ThreadStart(Run));
httpThread.Start();
isrunning = true;
}
catch(Exception ex) { ErrorMessage = ex.Message; }
}
private bool isrunning = false;
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool IsRunning()
{
return isrunning;
}
/// <summary>
/// 开始服务
/// </summary>
public void Start()
{
isrunning = false;
stopped = false;
try
{
if (listener == null || !listener.IsListening)
{
listener = new HttpListener();
listener.Prefixes.Add("http://"+ ListenerHost + ":" + port + "/");
//listener.Prefixes.Add(HTTPS_PREFIX + HTTPS_PORT + "/");
listener.Start();
}
if (httpThread == null || httpThread.ThreadState != ThreadState.Running)
{
httpThread = new Thread(new ThreadStart(Run));
httpThread.Start();
}
isrunning = true;
}
catch(Exception ex) { ErrorMessage = ex.Message; }
}
/// <summary>
/// 退出服务
/// </summary>
public void Exit()
{
stopped = true;
try
{
if (listener != null)
{
listener.Stop();
listener.Close();
}
if (httpThread != null)
{
httpThread.Interrupt();
}
listener = null;
httpThread = null;
}
catch (Exception ex) { ErrorMessage = ex.Message; }
isrunning = false;
}
/// <summary>
///
/// </summary>
~HttpServer()
{
Exit();
}
private void Run()
{
while (!stopped)
{
try
{
var r = listener.BeginGetContext(new AsyncCallback(RequestHandler), listener);
r.AsyncWaitHandle.WaitOne();
r.AsyncWaitHandle.Close();
}
catch (ThreadInterruptedException e1) { ErrorMessage = e1.Message; }
catch (HttpListenerException e2)
{
ErrorMessage = e2.Message;
}
}
}
private void RequestHandler(IAsyncResult r)
{
try
{
_RequestHandler(r);
}
catch (Exception e)
{
ErrorMessage = e.Message;
}
}
private void _RequestHandler(IAsyncResult r)
{
if (stopped) return;
var l = (HttpListener)r.AsyncState;
var ctx = l.EndGetContext(r);
var req = ctx.Request;
var resp = ctx.Response;
var html = "";
if(req.HttpMethod=="GET")
{
HttpRequest e = new HttpRequest();
e.Url = req.Url;
e.UrlReferrer = req.UrlReferrer;
OnHandleGETRequest?.Invoke(this,e);
resp.StatusCode = (int)e.StatusCode;
html = e.ReturnHtml;
}
else if(req.HttpMethod=="POST")
{
HttpRequest e = new HttpRequest
{
Url = req.Url,
UrlReferrer = req.UrlReferrer
};
var sr = new StreamReader(req.InputStream, Encoding.GetEncoding("GB2312"));
e.PostDataStr = sr.ReadToEnd();
e.PostData= RyWeb.WebDecode.UrlToData(e.PostDataStr);
sr.Close();
OnHandlePOSTRequest?.Invoke(this, e);
resp.StatusCode = (int)e.StatusCode;
html = e.ReturnHtml;
}
var buffer = Encoding.UTF8.GetBytes(html);
resp.ContentLength64 = buffer.Length;
resp.OutputStream.Write(buffer, 0, buffer.Length);
var outs = resp.OutputStream;
outs.Close();
resp.Close();
}
}
/// <summary>
///
/// </summary>
public class HttpRequest
{
/// <summary>
///
/// </summary>
public Uri Url { get; internal set; }
/// <summary>
///
/// </summary>
public string PostDataStr { get; internal set; } = "";
/// <summary>
///
/// </summary>
internal Tuple<string, IEnumerable<KeyValuePair<string, string>>> PostData { get; set; }
/// <summary>
///
/// </summary>
public string GetPostData(string Param)
{
return PostData.Get(Param);
}
/// <summary>
///
/// </summary>
public string GetPostData(string Param,string defValue)
{
return PostData.Get(Param, defValue);
}
/// <summary>
///
/// </summary>
public int GetPostData(string Param,int defValue)
{
return PostData.Get(Param, defValue);
}
/// <summary>
///
/// </summary>
public bool GetPostData(string Param, bool defValue)
{
return PostData.Get(Param, defValue);
}
/// <summary>
///
/// </summary>
public Uri UrlReferrer { get; internal set; }
/// <summary>
///
/// </summary>
public string ReturnHtml { get; set; } = "";
/// <summary>
///
/// </summary>
public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.OK;
}
}