#if NETFX using System; using System.Collections.Generic; using System.IO; using System.Web; namespace Apewer.Web { /// <summary>用于网站的服务程序。</summary> public class WebsiteProvider : ApiProvider { private HttpContext context; private HttpRequest request; private HttpResponse response; /// <summary>创建服务程序实例。</summary> /// <exception cref="ArgumentNullException"></exception> public WebsiteProvider(HttpContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); this.context = context; request = context.Request; response = context.Response; } #region Implement /// <summary>调用前的检查,返回错误信息。</summary> public override string PreInvoke() { return null; } /// <summary>读取请求前的检查,返回错误信息。</summary> public override string PreRead() { return null; } /// <summary>写入响应前的检查,返回错误信息。</summary> public override string PreWrite() { // 从 Response 头中移除 Server 和 X-Powered-By 属性。 #if NETFX var keys = new List<string>(response.Headers.AllKeys); #else var keys = new List<string>(response.Headers.Keys); #endif if (keys.Contains("Server")) response.Headers.Remove("Server"); if (keys.Contains("X-Powered-By")) response.Headers.Remove("X-Powered-By"); return null; } /// <summary>停止并关闭响应流。</summary> public override void End() => End(false); /// <summary>释放非托管资源。</summary> public override void Dispose() { } #endregion #region Request /// <summary>获取 HTTP 方法。</summary> public override Network.HttpMethod GetMethod() => ApiUtility.Method(request.HttpMethod); /// <summary>获取客户端的 IP 地址。</summary> public override string GetClientIP() => request.UserHostAddress; /// <summary>获取请求的 URL。</summary> public override Uri GetUrl() => request.Url; /// <summary>获取请求的 Referrer。</summary> public override string GetReferrer() => request.UrlReferrer == null ? null : request.UrlReferrer.OriginalString; /// <summary>获取请求的头。</summary> public override StringPairs GetHeaders() => StringPairs.From(request.Headers); /// <summary>获取请求的内容类型。</summary> public override string GetContentType() => request.ContentType; /// <summary>获取请求的内容长度。</summary> public override long GetContentLength() => request.ContentLength; /// <summary>获取请求的内容。</summary> public override Stream RequestBody() => request.InputStream; #endregion #region Response /// <summary>设置 HTTP 状态。</summary> public override void SetStatus(string status) => response.Status = status; /// <summary>设置响应的头。</summary> public override string SetHeader(string name, string value) { if (response == null || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value)) return "参数无效。"; try { #if NET20 response.AddHeader(name, value); #else response.Headers.Add(name, value); #endif return null; } catch (Exception ex) { return ex.Message; } } /// <summary>设置响应的缓存秒数,设置为 0 即不允许缓存。</summary> public override void SetCache(int seconds) { if (seconds > 0) { response.CacheControl = "public"; response.Cache.SetCacheability(HttpCacheability.Public); response.Cache.SetMaxAge(TimeSpan.FromSeconds(seconds)); response.Cache.SetProxyMaxAge(TimeSpan.FromSeconds(seconds)); response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); } else { response.CacheControl = "no-cache"; response.Cache.SetCacheability(HttpCacheability.NoCache); response.Cache.SetNoStore(); SetHeader("Pragma", "no-cache"); } } /// <summary>设置响应的缓存秒数。</summary> public override void SetContentType(string value) => response.ContentType = value; /// <summary>设置响应的内容长度。</summary> public override void SetContentLength(long value) => SetHeader("Content-Length", value.ToString()); /// <summary>设置响应重定向。</summary> /// <remarks>响应 302 状态。</remarks> public override void SetRedirect(string location) { try { response.Redirect(location, true); } catch { } } /// <summary>获取 Response 流。</summary> public override Stream ResponseBody() => response.OutputStream; #endregion #region This /// <summary>停止并关闭响应流。可指定向发送缓冲区的数据。</summary> public void End(bool flush) { try { if (flush) response.Flush(); } catch { } try { response.Close(); } catch { } // try { response.End(); } catch { } } /// <summary>获取 Cookies。</summary> public StringPairs GetCookies() { var sp = new StringPairs(); if (request != null && request.Cookies != null) { #if NETFX foreach (var key in request.Cookies.AllKeys) { try { var cookie = request.Cookies[key]; var value = cookie.Value ?? ""; sp.Add(new KeyValuePair<string, string>(key, value)); } catch { } } #else foreach (var key in request.Cookies.Keys) { try { var value = request.Cookies[key] ?? ""; sp.Add(new KeyValuePair<string, string>(key, value)); } catch { } } #endif } return sp; } /// <summary>设置响应的 Cookie。</summary> public static string SetCookie(HttpResponse response, string key, string value) { if (response == null) return null; var k = key.ToTrim(); var v = value.ToTrim(); if (k.IsEmpty()) return "参数 Key 无效。"; try { #if NETFX var cookie = new HttpCookie(k, v); var now = DateTime.Now; cookie.Expires = v.IsEmpty() ? now.AddDays(-1) : now.AddYears(1); response.SetCookie(cookie); #else // var options = new CookieOptions(); // response.Cookies.Append(key, value, options); response.Cookies.Append(key, value); #endif return null; } catch (Exception ex) { return ex.Message; } } internal static void TrimHeaders(HttpApplication context) { context.PreSendRequestHeaders += (s, e) => { var context = HttpContext.Current; if (context == null) return; var response = context.Response; // 从 Response 头中移除 Server 和 X-Powered-By 属性。 var keys = new List<string>(response.Headers.AllKeys); if (keys.Contains("Server")) response.Headers.Remove("Server"); if (keys.Contains("X-Powered-By")) response.Headers.Remove("X-Powered-By"); }; } #endregion } } #endif