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.

227 lines
7.5 KiB

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