You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
7.7 KiB

4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
11 months ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
  1. #if NETCORE
  2. using Apewer.Network;
  3. using Microsoft.AspNetCore.Http;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Text;
  8. namespace Apewer.Web
  9. {
  10. /// <summary>用于网站的服务程序。</summary>
  11. public class AspNetCoreProvider : ApiProvider<HttpContext>
  12. {
  13. private HttpContext context;
  14. private HttpRequest request;
  15. private HttpResponse response;
  16. /// <summary>HttpContext</summary>
  17. public override HttpContext Context { get => context; }
  18. /// <summary>创建服务程序实例。</summary>
  19. /// <exception cref="ArgumentNullException"></exception>
  20. public AspNetCoreProvider(HttpContext context)
  21. {
  22. if (context == null) throw new ArgumentNullException(nameof(context));
  23. this.context = context;
  24. request = context.Request;
  25. response = context.Response;
  26. }
  27. #region Request
  28. /// <summary>获取 HTTP 方法。</summary>
  29. public override Network.HttpMethod GetMethod() => ApiUtility.Method(request.Method);
  30. /// <summary>获取客户端的 IP 地址。</summary>
  31. public override string GetClientIP() => request.HttpContext.Connection.RemoteIpAddress.ToString();
  32. /// <summary>获取请求的 URL。</summary>
  33. public override Uri GetUrl()
  34. {
  35. var https = request.IsHttps;
  36. var port = Context.Connection.LocalPort;
  37. var query = request.QueryString == null ? null : request.QueryString.Value;
  38. var sb = new StringBuilder();
  39. sb.Append(https ? "https://" : "http://");
  40. sb.Append(request.Host.Host ?? "");
  41. if ((https && port != 443) || (!https && port != 80))
  42. {
  43. sb.Append(":");
  44. sb.Append(port);
  45. }
  46. sb.Append(request.Path);
  47. if (!string.IsNullOrEmpty(query))
  48. {
  49. if (!query.StartsWith("?")) sb.Append("?");
  50. sb.Append(query);
  51. }
  52. var url = sb.ToString();
  53. var uri = new Uri(url);
  54. return uri;
  55. }
  56. /// <summary>获取请求的 Referrer。</summary>
  57. public override string GetReferrer() => null;
  58. /// <summary>获取请求的头。</summary>
  59. public override HttpHeaders GetHeaders()
  60. {
  61. var headers = request.Headers;
  62. var result = new HttpHeaders();
  63. if (headers == null) return result;
  64. foreach (var key in headers.Keys)
  65. {
  66. if (string.IsNullOrEmpty(key)) continue;
  67. try
  68. {
  69. var value = headers[key];
  70. if (string.IsNullOrEmpty(value)) continue;
  71. result.Add(key, value);
  72. }
  73. catch { }
  74. }
  75. return result;
  76. }
  77. /// <summary>获取请求的内容类型。</summary>
  78. public override string GetContentType() => request.ContentType;
  79. /// <summary>获取请求的内容长度。</summary>
  80. public override long GetContentLength() => request.ContentLength ?? -1L;
  81. /// <summary>获取请求的内容。</summary>
  82. public override Stream RequestBody() => request.Body;
  83. #endregion
  84. #region Response
  85. /// <summary>设置 HTTP 状态。</summary>
  86. public override void SetStatus(int status, int subStatus = 0) => response.StatusCode = status;
  87. /// <summary>设置响应的头。</summary>
  88. public override string SetHeader(string name, string value)
  89. {
  90. try
  91. {
  92. response.Headers.Add(name, value);
  93. }
  94. catch (Exception ex)
  95. {
  96. Logger.Internals.Error(nameof(AspNetCoreProvider), nameof(SetHeader), ex.Message(), name, value);
  97. return ex.Message;
  98. }
  99. return null;
  100. }
  101. /// <summary>设置响应的缓存秒数,设置为 0 即不允许缓存。</summary>
  102. public override void SetCache(int seconds)
  103. {
  104. if (seconds > 0)
  105. {
  106. SetHeader("Cache-Control", $"public, max-age={seconds}, s-maxage={seconds}");
  107. }
  108. else
  109. {
  110. SetHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  111. SetHeader("Pragma", "no-cache");
  112. }
  113. }
  114. /// <summary>设置响应的缓存秒数。</summary>
  115. public override void SetContentType(string value) => response.ContentType = value;
  116. /// <summary>设置响应的内容长度。</summary>
  117. public override void SetContentLength(long value) => response.ContentLength = value;
  118. /// <summary>设置响应重定向。</summary>
  119. public override void SetRedirect(string location) => SetRedirect(location, false);
  120. /// <summary>获取 Response 流。</summary>
  121. public override Stream ResponseBody() => response.Body;
  122. #endregion
  123. #region This
  124. /// <summary>将客户端重新定向到新 URL。</summary>
  125. /// <remarks>默认响应 302 状态。可指定 permanent = true 以响应 301 状态。</remarks>
  126. public void SetRedirect(string location, bool permanent = false)
  127. {
  128. try { response.Redirect(location, permanent); } catch { }
  129. }
  130. private static void Async(Stream source, Stream destination, Func<long, bool> progress = null, int buffer = 4096, Action after = null)
  131. {
  132. if (source == null || !source.CanRead || destination == null || !destination.CanWrite)
  133. {
  134. after?.Invoke();
  135. return;
  136. }
  137. Async(source, destination, progress, buffer, after, 0L);
  138. }
  139. private static void Async(Stream source, Stream destination, Func<long, bool> progress, int buffer, Action after, long total)
  140. {
  141. // 缓冲区。
  142. var limit = buffer < 1 ? 1 : buffer;
  143. var temp = new byte[limit];
  144. // 读取一次。
  145. try
  146. {
  147. source.BeginRead(temp, 0, limit, (ar1) =>
  148. {
  149. var count = source.EndRead(ar1);
  150. if (count > 0)
  151. {
  152. destination.BeginWrite(temp, 0, count, (ar2) =>
  153. {
  154. destination.EndWrite(ar2);
  155. total += count;
  156. if (progress != null)
  157. {
  158. var @continue = progress.Invoke(total);
  159. if (!@continue)
  160. {
  161. after?.Invoke();
  162. return;
  163. }
  164. }
  165. Async(source, destination, progress, buffer, after, total);
  166. }, null);
  167. }
  168. else after?.Invoke();
  169. }, null);
  170. }
  171. catch { }
  172. }
  173. /// <summary>解析 URL 的查询字符串,获取所有已解码的参数。</summary>
  174. public static StringPairs ParseQuery(HttpRequest request)
  175. {
  176. if (request == null) return new StringPairs();
  177. var sp = new StringPairs();
  178. if (request.Query == null) return sp;
  179. var keys = request.Query.Keys;
  180. sp.Capacity = keys.Count;
  181. foreach (var key in keys)
  182. {
  183. sp.Add(key, request.Query[key]);
  184. }
  185. sp.Capacity = sp.Count;
  186. return sp;
  187. }
  188. #endregion
  189. }
  190. }
  191. #endif