HttpServer.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using DaJiaoYan.Utils;
  2. using Newtonsoft.Json;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Net;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Web;
  10. namespace DaJiaoYan.Services
  11. {
  12. public class HttpHandler
  13. {
  14. public readonly AsyncHttpServer HttpServer;
  15. public readonly string path;
  16. private ResponseData DefaultResponse = new ResponseData { Code = 405 };
  17. public HttpHandler(AsyncHttpServer httpServer, string path = null)
  18. {
  19. HttpServer = httpServer;
  20. this.path = path;
  21. }
  22. public virtual void Get(HttpListenerRequest request, HttpListenerResponse response)
  23. {
  24. //StaticFile(request, ref response, (HttpListenerRequest req, HttpListenerResponse rep) =>
  25. //{
  26. // Json(ref rep, ref DefaultResponse);
  27. //});
  28. Json(ref response, ref DefaultResponse);
  29. }
  30. public virtual void Post(HttpListenerRequest request, HttpListenerResponse response)
  31. {
  32. Json(ref response, ref DefaultResponse);
  33. }
  34. public virtual void Patch(HttpListenerRequest request, HttpListenerResponse response)
  35. {
  36. Json(ref response, ref DefaultResponse);
  37. }
  38. public virtual void Put(HttpListenerRequest request, HttpListenerResponse response)
  39. {
  40. Json(ref response, ref DefaultResponse);
  41. }
  42. public virtual void Delete(HttpListenerRequest request, HttpListenerResponse response)
  43. {
  44. Json(ref response, ref DefaultResponse);
  45. }
  46. /// <summary>
  47. /// 输出数据
  48. /// </summary>
  49. /// <param name="response"></param>
  50. /// <param name="bytes"></param>
  51. public virtual void Response(ref HttpListenerResponse response, ref byte[] bytes)
  52. {
  53. if (bytes != null)
  54. {
  55. using (var stream = response.OutputStream)
  56. {
  57. ///获取数据,要返回给接口的
  58. try
  59. {
  60. stream.Write(bytes, 0, bytes.Length);
  61. }
  62. catch { }
  63. }
  64. }
  65. response.Close();
  66. }
  67. /// <summary>
  68. /// 响应Json格式数据
  69. /// </summary>
  70. /// <param name="response"></param>
  71. /// <param name="result"></param>
  72. public virtual void Json(ref HttpListenerResponse response, ref ResponseData result)
  73. {
  74. response.AddHeader("Content-type", "application/json");//添加响应头信息
  75. response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  76. response.AddHeader("Pragma", "no-cache");
  77. response.AddHeader("Expires", "0");
  78. response.StatusCode = result.Code;
  79. //response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
  80. response.ContentEncoding = Encoding.UTF8;
  81. //string d = YxqService.Utils.Json.Encode(result);
  82. var data = Encoding.UTF8.GetBytes(Utils.Json.Encode(result));
  83. Response(ref response, ref data);
  84. }
  85. }
  86. /// <summary>
  87. /// 响应数据格式
  88. /// </summary>
  89. public struct ResponseData
  90. {
  91. [JsonProperty(PropertyName = "code")]
  92. public int Code { get; set; }
  93. [JsonProperty(PropertyName = "msg")]
  94. public object Msg { get; set; }
  95. [JsonProperty(PropertyName = "errors")]
  96. public object Errors { get; set; }
  97. [JsonProperty(PropertyName = "data")]
  98. public object Data { get; set; }
  99. }
  100. public class AsyncHttpServer
  101. {
  102. private readonly HttpListener _listener;
  103. private bool _isRunning;
  104. /// <summary>
  105. /// 中间件方法
  106. /// </summary>
  107. /// <param name="request"></param>
  108. /// <param name="response"></param>
  109. /// <param name="result"></param>
  110. /// <returns></returns>
  111. public delegate bool Middleware(HttpListenerRequest request, HttpListenerResponse response);
  112. /// <summary>
  113. /// 接口方法
  114. /// </summary>
  115. /// <param name="request"></param>
  116. /// <param name="result"></param>
  117. public delegate void HttpHandle(HttpListenerRequest request, HttpListenerResponse response);
  118. /// <summary>
  119. /// 中间件数组
  120. /// </summary>
  121. private readonly List<Middleware> MiddleWares = new List<Middleware>();
  122. /// <summary>
  123. /// 路由字典
  124. /// </summary>
  125. private readonly Dictionary<string, HttpHandler> Prefixes = new Dictionary<string, HttpHandler>();
  126. /// <summary>
  127. /// 默认接口
  128. /// </summary>
  129. private readonly HttpHandler DefaultHandler;
  130. public readonly string Root;
  131. public readonly int Port;
  132. public readonly string Host;
  133. public readonly string Scheme;
  134. /// <summary>
  135. /// 监听地址
  136. /// </summary>
  137. public readonly string Listener;
  138. public AsyncHttpServer(string root, string host = "127.0.0.1", int port = 7000, string scheme = "http")
  139. {
  140. this.Root = root;
  141. DefaultHandler = new HttpHandler(this, root);
  142. this.Port = port;
  143. this.Host = host;
  144. this.Scheme = scheme;
  145. Listener = $"{scheme}://{host}:{port}/";
  146. _listener = new HttpListener();
  147. _listener.Prefixes.Add(Listener);
  148. Prefixes.Add("", DefaultHandler);
  149. }
  150. /// <summary>
  151. /// 注册中间件
  152. /// </summary>
  153. /// <param name="func"></param>
  154. public void RegisterMiddleware(Middleware func)
  155. {
  156. MiddleWares.Add(func);
  157. }
  158. public void RegisterPrefix(string prefix, HttpHandler handler)
  159. {
  160. Prefixes.Add(prefix, handler);
  161. }
  162. public async Task StartAsync()
  163. {
  164. _isRunning = true;
  165. _listener.Start();
  166. Console.WriteLine($"Server started on {string.Join(", ", _listener.Prefixes)}");
  167. try
  168. {
  169. while (_isRunning)
  170. {
  171. var context = await _listener.GetContextAsync();
  172. _ = Task.Factory.StartNew(() => ProcessRequest(context));
  173. }
  174. }
  175. catch (Exception ex)
  176. {
  177. Console.WriteLine($"Server error: {ex.Message}");
  178. }
  179. }
  180. public void Stop()
  181. {
  182. _isRunning = false;
  183. _listener.Stop();
  184. _listener.Close();
  185. Console.WriteLine("Server stopped");
  186. }
  187. private bool ProcessMiddlewares(HttpListenerContext context)
  188. {
  189. bool res = true;
  190. // 中间件处理
  191. foreach (var mw in MiddleWares)
  192. {
  193. if (!mw(context.Request, context.Response))
  194. {
  195. context.Response.Close();
  196. res = false;
  197. break;
  198. }
  199. }
  200. return res;
  201. }
  202. private void ProcessRequest(HttpListenerContext context)
  203. {
  204. if (!ProcessMiddlewares(context))
  205. {
  206. return;
  207. }
  208. var request = context.Request;
  209. var response = context.Response;
  210. try
  211. {
  212. Prefixes.TryGetValue(request.Url.AbsolutePath, out var r);
  213. if (r == null)
  214. {
  215. Prefixes.TryGetValue("", out r);
  216. }
  217. HttpHandle act;
  218. if (r == null)
  219. {
  220. response.StatusCode = 404;
  221. response.Close();
  222. act = DefaultHandler.Get;
  223. }
  224. else
  225. {
  226. switch (request.HttpMethod.ToUpper())
  227. {
  228. case "POST":
  229. act = r.Post;
  230. break;
  231. case "PUT":
  232. act = r.Put;
  233. break;
  234. case "DELETE":
  235. act = r.Delete;
  236. break;
  237. case "PATCH":
  238. act = r.Patch;
  239. break;
  240. default:
  241. act = r.Get;
  242. break;
  243. }
  244. }
  245. act?.Invoke(request, response);
  246. }
  247. catch (Exception e)
  248. {
  249. Log.WriteLine(e.ToString());
  250. response.StatusCode = 404;
  251. }
  252. finally
  253. {
  254. //response.Close();
  255. }
  256. }
  257. public Dictionary<string, string> ParseForm(ref HttpListenerRequest request)
  258. {
  259. Dictionary<string, string> res = new Dictionary<string, string>();
  260. string content;
  261. using (Stream stream = request.InputStream)
  262. using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
  263. {
  264. content = reader.ReadToEnd();
  265. }
  266. if (!string.IsNullOrEmpty(content))
  267. {
  268. foreach (var arg in content.Split('&'))
  269. {
  270. var n = arg.IndexOf('=');
  271. if (n > 0)
  272. {
  273. res[arg.Substring(0, n)] = HttpUtility.UrlDecode(arg.Substring(n + 1));
  274. }
  275. }
  276. }
  277. return res;
  278. }
  279. }
  280. }