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.

237 lines
7.8 KiB

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