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.

241 lines
8.0 KiB

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
11 months ago
4 years ago
4 years ago
4 years ago
  1. #if NETFX
  2. using Apewer.Network;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Web;
  7. namespace Apewer.Web
  8. {
  9. /// <summary>用于网站的服务程序。</summary>
  10. public class WebsiteProvider : ApiProvider<HttpContext>
  11. {
  12. private HttpContext context;
  13. private HttpRequest request;
  14. private HttpResponse response;
  15. /// <summary>HttpContext</summary>
  16. public override HttpContext Context { get => context; }
  17. /// <summary>创建服务程序实例。</summary>
  18. /// <exception cref="ArgumentNullException"></exception>
  19. public WebsiteProvider(HttpContext context)
  20. {
  21. if (context == null) throw new ArgumentNullException(nameof(context));
  22. this.context = context;
  23. request = context.Request;
  24. response = context.Response;
  25. }
  26. #region Implement
  27. /// <summary>写入响应前的检查,返回错误信息。</summary>
  28. public override string PreWrite()
  29. {
  30. // 从 Response 头中移除 Server 和 X-Powered-By 属性。
  31. #if NETFX
  32. var keys = new List<string>(response.Headers.AllKeys);
  33. #else
  34. var keys = new List<string>(response.Headers.Keys);
  35. #endif
  36. if (keys.Contains("Server")) response.Headers.Remove("Server");
  37. if (keys.Contains("X-Powered-By")) response.Headers.Remove("X-Powered-By");
  38. return null;
  39. }
  40. /// <summary></summary>
  41. public override void Sent() => response.Flush();
  42. /// <summary>停止并关闭响应流。</summary>
  43. public override void End() => End(false);
  44. #endregion
  45. #region Request
  46. /// <summary>获取 HTTP 方法。</summary>
  47. public override Network.HttpMethod GetMethod() => ApiUtility.Method(request.HttpMethod);
  48. /// <summary>获取客户端的 IP 地址。</summary>
  49. public override string GetClientIP() => request.UserHostAddress;
  50. /// <summary>获取请求的 URL。</summary>
  51. public override Uri GetUrl() => request.Url;
  52. /// <summary>获取请求的 Referrer。</summary>
  53. public override string GetReferrer() => request.UrlReferrer == null ? null : request.UrlReferrer.OriginalString;
  54. /// <summary>获取请求的头。</summary>
  55. public override HttpHeaders GetHeaders() => new HttpHeaders(request.Headers);
  56. /// <summary>获取请求的内容类型。</summary>
  57. public override string GetContentType() => request.ContentType;
  58. /// <summary>获取请求的内容长度。</summary>
  59. public override long GetContentLength() => request.ContentLength;
  60. /// <summary>获取请求的内容。</summary>
  61. public override Stream RequestBody() => request.InputStream;
  62. #endregion
  63. #region Response
  64. /// <summary>设置 HTTP 状态。</summary>
  65. public override void SetStatus(int status, int subStatus = 0)
  66. {
  67. response.StatusCode = status;
  68. if (subStatus > 0) response.SubStatusCode = subStatus;
  69. }
  70. /// <summary>设置响应的头。</summary>
  71. public override string SetHeader(string name, string value)
  72. {
  73. if (response == null || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value)) return "参数无效。";
  74. try
  75. {
  76. #if NET20
  77. response.AddHeader(name, value);
  78. #else
  79. response.Headers.Add(name, value);
  80. #endif
  81. return null;
  82. }
  83. catch (Exception ex) { return ex.Message; }
  84. }
  85. /// <summary>设置响应的缓存秒数,设置为 0 即不允许缓存。</summary>
  86. public override void SetCache(int seconds)
  87. {
  88. if (seconds > 0)
  89. {
  90. response.CacheControl = "public";
  91. response.Cache.SetCacheability(HttpCacheability.Public);
  92. response.Cache.SetMaxAge(TimeSpan.FromSeconds(seconds));
  93. response.Cache.SetProxyMaxAge(TimeSpan.FromSeconds(seconds));
  94. response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
  95. }
  96. else
  97. {
  98. response.CacheControl = "no-cache";
  99. response.Cache.SetCacheability(HttpCacheability.NoCache);
  100. response.Cache.SetNoStore();
  101. SetHeader("Pragma", "no-cache");
  102. }
  103. }
  104. /// <summary>设置响应的缓存秒数。</summary>
  105. public override void SetContentType(string value) => response.ContentType = value;
  106. /// <summary>设置响应的内容长度。</summary>
  107. public override void SetContentLength(long value) => SetHeader("Content-Length", value.ToString());
  108. /// <summary>设置响应重定向。</summary>
  109. /// <remarks>响应 302 状态。</remarks>
  110. public override void SetRedirect(string location)
  111. {
  112. try { response.Redirect(location, true); } catch { }
  113. }
  114. /// <summary>获取 Response 流。</summary>
  115. public override Stream ResponseBody() => response.OutputStream;
  116. #endregion
  117. #region This
  118. /// <summary>停止并关闭响应流。可指定向发送缓冲区的数据。</summary>
  119. public void End(bool flush)
  120. {
  121. try { if (flush) response.Flush(); } catch { }
  122. try { response.Close(); } catch { }
  123. // try { response.End(); } catch { }
  124. }
  125. /// <summary>获取 Cookies。</summary>
  126. public StringPairs GetCookies()
  127. {
  128. var sp = new StringPairs();
  129. if (request != null && request.Cookies != null)
  130. {
  131. #if NETFX
  132. foreach (var key in request.Cookies.AllKeys)
  133. {
  134. try
  135. {
  136. var cookie = request.Cookies[key];
  137. var value = cookie.Value ?? "";
  138. sp.Add(new KeyValuePair<string, string>(key, value));
  139. }
  140. catch { }
  141. }
  142. #else
  143. foreach (var key in request.Cookies.Keys)
  144. {
  145. try
  146. {
  147. var value = request.Cookies[key] ?? "";
  148. sp.Add(new KeyValuePair<string, string>(key, value));
  149. }
  150. catch { }
  151. }
  152. #endif
  153. }
  154. return sp;
  155. }
  156. /// <summary>设置响应的 Cookie。</summary>
  157. public static string SetCookie(HttpResponse response, string key, string value)
  158. {
  159. if (response == null) return null;
  160. var k = key.ToTrim();
  161. var v = value.ToTrim();
  162. if (k.IsEmpty()) return "参数 Key 无效。";
  163. try
  164. {
  165. #if NETFX
  166. var cookie = new HttpCookie(k, v);
  167. var now = DateTime.Now;
  168. cookie.Expires = v.IsEmpty() ? now.AddDays(-1) : now.AddYears(1);
  169. response.SetCookie(cookie);
  170. #else
  171. // var options = new CookieOptions();
  172. // response.Cookies.Append(key, value, options);
  173. response.Cookies.Append(key, value);
  174. #endif
  175. return null;
  176. }
  177. catch (Exception ex)
  178. {
  179. return ex.Message;
  180. }
  181. }
  182. internal static void TrimHeaders(HttpApplication context)
  183. {
  184. context.PreSendRequestHeaders += (s, e) =>
  185. {
  186. var context = HttpContext.Current;
  187. if (context == null) return;
  188. var response = context.Response;
  189. // 从 Response 头中移除 Server 和 X-Powered-By 属性。
  190. var keys = new List<string>(response.Headers.AllKeys);
  191. if (keys.Contains("Server")) response.Headers.Remove("Server");
  192. if (keys.Contains("X-Powered-By")) response.Headers.Remove("X-Powered-By");
  193. };
  194. }
  195. #endregion
  196. }
  197. }
  198. #endif