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
241 lines
8.0 KiB
#if NETFX
|
|
|
|
using Apewer.Network;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Web;
|
|
|
|
namespace Apewer.Web
|
|
{
|
|
|
|
/// <summary>用于网站的服务程序。</summary>
|
|
public class WebsiteProvider : ApiProvider<HttpContext>
|
|
{
|
|
|
|
private HttpContext context;
|
|
private HttpRequest request;
|
|
private HttpResponse response;
|
|
|
|
/// <summary>HttpContext</summary>
|
|
public override HttpContext Context { get => context; }
|
|
|
|
/// <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 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 Sent() => response.Flush();
|
|
|
|
/// <summary>停止并关闭响应流。</summary>
|
|
public override void End() => End(false);
|
|
|
|
#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 HttpHeaders GetHeaders() => new HttpHeaders(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(int status, int subStatus = 0)
|
|
{
|
|
response.StatusCode = status;
|
|
if (subStatus > 0) response.SubStatusCode = subStatus;
|
|
}
|
|
|
|
/// <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
|
|
|