| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -10,61 +10,74 @@ namespace Apewer.Web | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    public class StaticController : ApiController | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>允许服务器端包含(Server Side Include)。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认值:允许。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected bool AllowSSI { get; set; } = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>当执行目录且没有默认文档时,枚举子目录和子文件。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认值:不允许。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected bool AllowEnumerate { get; set; } = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取已解析的站点根目录。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected string Root { get => _root?.Value; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        List<string> PathSegments; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region 初始化
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Func<StaticController, JumpStatement> _initializer = null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Class<string> _root = null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary></summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        public StaticController() : base((c) => { ((StaticController)c).Initialize(); return false; }) { } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary></summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        public StaticController(Func<StaticController, JumpStatement> initializer) : base((c) => { ((StaticController)c).Initialize(); return false; }) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            _initializer = initializer; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        void Initialize() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (Request == null || Request.Url == null) return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var absolute = Request.Url.AbsolutePath; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var split = absolute == null ? new string[0] : absolute.Split('/', '\\'); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            PathSegments = new List<string>(split.Length); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var item in split) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (_initializer != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var trim = TextUtility.Trim(TextUtility.DecodeUrl(item)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (string.IsNullOrEmpty(trim)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (trim == "." || trim == "..") continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                PathSegments.Add(trim); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var jump = _initializer.Invoke(this); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (jump == JumpStatement.Break) return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            absolute = TextUtility.Join("/", PathSegments); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var path = MapPath(absolute); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (PathSegments.Count < 1) Directory(GetRoot()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else if (IsBlocked(PathSegments[0])) Respond404(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else if (StorageUtility.FileExists(path)) File(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else if (StorageUtility.DirectoryExists(path)) Directory(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else Respond404(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region virtual
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 获取相对路径
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var urlPath = GetUrlPath(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(urlPath)) return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应 404 状态。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:设置状态为 404,不输出内容。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Respond404(string path) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            Response.Model = new ApiStatusModel(404); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 内置的处理程序
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            ApiUtility.StopReturn(Response); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            Execute(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应 403 状态。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:设置状态为 403,不输出内容。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Respond403(string path) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region 自定义
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>允许服务器端包含(Server Side Include)。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认值:允许。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected bool AllowSSI { get; set; } = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>允许 GetRoot 方法访问应用程序目录。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认值:不允许。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected bool AllowApplicationPath { get; set; } = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取已解析的站点根目录。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected string Root { get => _root?.Value; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>执行路径。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Execute(string urlPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            Response.Model = new ApiStatusModel(403); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 自定义处理
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var model = GetModel(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (model != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Response.Model = model; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 自定义处理
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var result = GetResult(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (result != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Response.Model = result; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            InternalExecute(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取此静态站点的目录。</summary>
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -111,156 +124,365 @@ namespace Apewer.Web | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return @static; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            _root = new Class<string>(app); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return app; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (AllowApplicationPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                _root = new Class<string>(app); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return app; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                _root = new Class<string>(null); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取 URL 路径。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual string GetUrlPath() => Request.Url.AbsolutePath; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取响应结果。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual IActionResult GetResult(string urlPath) => null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>获取响应结果。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual ApiModel GetModel(string urlPath) => null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>加载 Web.zip 文件。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual Dictionary<string, byte[]> LoadWebZip() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var names = new string[] { "Web.zip", "web.zip" }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var name in names) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var path = StorageUtility.CombinePath(RuntimeUtility.ApplicationPath, name); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (StorageUtility.FileExists(path)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var data = StorageUtility.ReadFile(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var dict = BytesUtility.FromZip(data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return dict; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>从扩展名获取内容类型。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual string ContentType(string extension) => NetworkUtility.Mime(extension); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>从扩展名和文件路径获取过期时间。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认值:0,不缓存。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual int Expires(string extension, string path) => 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region 开放方法
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应重定向。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void RespondRedirect(string urlPath, string location) => Response.Model = new ApiRedirectModel(location); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应 400 状态。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:设置状态为 400,不输出内容。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Respond400(string path, string reason) => Response.Model = new ApiStatusModel(400); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应 404 状态。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:设置状态为 404,不输出内容。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Respond404(string urlPath) => Response.Model = new ApiStatusModel(404); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>响应 403 状态。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:设置状态为 403,不输出内容。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Respond403(string urlPath) => Response.Model = new ApiStatusModel(403); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region 内置的执行程序
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const bool WipeBom = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 默认文档的文件名
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        static string[] DefaultFileNames = new string[] { "index.html", "index.htm", "default.html", "default.htm" }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 文件名中不允许出现的字符
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        static char[] InvalidFileNameChars = Path.GetInvalidFileNameChars(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>已解析到本地文本路径,执行此路径。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:输出文件内容,文件不存在时输出 404 状态。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void File(string path) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Zip 文件的缓存
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        static Dictionary<Type, Dictionary<string, byte[]>> WebZips = new Dictionary<Type, Dictionary<string, byte[]>>(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 解析 URL 的路径,获取本地路径。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string MapPath(string urlPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!System.IO.File.Exists(path)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var path = GetRoot(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (path.IsEmpty()) return ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(urlPath)) return path; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var split in urlPath.Split('/', '\\')) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Respond404(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var segment = split.ToTrim(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (segment == null || segment == "" || segment == "." || segment == "..") continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                path = StorageUtility.CombinePath(path, segment); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return path; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        void InternalExecute(string urlPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (urlPath.IsEmpty()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Respond400(urlPath, "请求的 URL 路径无效。"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 获取文件扩展名。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var ext = Path.GetExtension(path).Lower(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (ext.Length > 1 && ext.StartsWith(".")) ext = ext.Substring(1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 检查路径
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var urlIsDir = urlPath.EndsWith("/") || urlPath.EndsWith("\\"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var urlExt = null as string; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var urlIsHtml = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var segments = new List<string>(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var split = urlPath == null ? new string[0] : urlPath.Split('/', '\\'); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                segments.Capacity = split.Length; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                foreach (var item in split) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var segment = TextUtility.DecodeUrl(item).Trim(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (string.IsNullOrEmpty(segment)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (segment == "." || segment == "..") continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // 检查无效字符
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    foreach (var c in segment) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (Array.IndexOf(InvalidFileNameChars, c) > -1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            Respond400(urlPath, $"请求的路径中含有无效字符。"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    segments.Add(segment); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 重置 UrlPath
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                urlPath = "/" + segments.Join("/"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (segments.Count > 0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // 请求筛选
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (IsBlocked(segments[0])) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        Respond404(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    urlExt = segments[segments.Count - 1].ToLower().Split('.').Last(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    urlIsHtml = urlExt == "html" || urlExt == "htm" || urlExt == "shtml"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 本地存储路径
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var storagePath = MapPath(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 按扩展名获取缓存过期时间。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var expires = Expires(ext, path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 本地文件
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (StorageUtility.FileExists(storagePath)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ExecuteFile(storagePath, urlPath, urlExt, urlIsHtml); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 按扩展名获取 Content-Type。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var type = ContentType(ext); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(type)) type = NetworkUtility.Mime(ext); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 目录
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (StorageUtility.DirectoryExists(storagePath)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var filePath = SearchDefaultFile(storagePath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (!string.IsNullOrEmpty(filePath)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (urlIsDir) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        ExecuteFile(filePath, urlPath, urlExt, urlIsHtml); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        var location = urlPath + "/"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        RespondRedirect(urlPath, location); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Server Side Includes
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (AllowSSI && ext == "html" || ext == "htm" || ext == "shtml") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // WebZip
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var webZip = GetWebZip(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (webZip != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var html = ReadWithSSI(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var bytes = html.Bytes(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 文件
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (webZip.TryGetValue(urlPath, out var data)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        ExecuteFile(data, urlExt, urlIsHtml); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 尝试匹配默认文档
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                foreach (var defaultName in DefaultFileNames) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var defaultPath = TextUtility.AssureEnds(urlPath, "/") + defaultName; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (webZip.TryGetValue(defaultPath, out var data)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (urlIsDir) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            ExecuteFile(data, defaultName, true); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            var location = TextUtility.AssureEnds(urlPath, "/"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            RespondRedirect(urlPath, location); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var model = new ApiBytesModel(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (expires > 0) model.Expires = expires; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                model.ContentType = type; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                model.Bytes = bytes; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 未知
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            Respond404(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        void ExecuteFile(string storagePath, string urlPath, string urlExt, bool urlIsHtml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var contentType = ContentType(urlExt); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (urlIsHtml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var text = ReadTextFile(urlPath, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var model = new ApiTextModel(text, contentType); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Response.Model = model; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var stream = StorageUtility.OpenFile(path, true); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var model = new ApiStreamModel(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (expires > 0) model.Expires = expires; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                model.ContentType = type; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                model.AutoDispose = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                model.Stream = stream; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                try | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var stream = StorageUtility.OpenFile(storagePath, true); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var model = new ApiStreamModel(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    model.ContentType = contentType; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    model.AutoDispose = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    model.Stream = stream; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    Response.Model = model; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                catch (Exception ex) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    Respond400(storagePath, $"<{ex.GetType().Name}> {ex.Message}"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        void ExecuteFile(byte[] data, string urlExt, bool urlIsHtml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var contentType = ContentType(urlExt); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (urlIsHtml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var text = data.Text(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                text = ServerSideIncludes(text, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var model = new ApiTextModel(text, contentType); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Response.Model = model; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var model = new ApiBytesModel(data, contentType); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Response.Model = model; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>已解析到本地目录路径,执行此路径。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <remarks>默认:输出文件内容,文件不存在时输出 404 状态。</remarks>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected virtual void Directory(string path) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>读取文本文件。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string ReadTextFile(string urlPath, int recursive) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!System.IO.Directory.Exists(path)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 主文件保留原有的 BOM
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var wipeBom = recursive > 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 本地文件
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var path = MapPath(urlPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (StorageUtility.FileExists(path)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                Respond404(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var data = StorageUtility.ReadFile(path, wipeBom); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var text = data.Text(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                text = ServerSideIncludes(text, recursive); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return text; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var @default = Default(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!string.IsNullOrEmpty(@default)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Zip
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var webZip = GetWebZip(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (webZip != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                File(@default); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (webZip.TryGetValue(urlPath, out var data)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var text = data.Text(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    text = ServerSideIncludes(text, recursive); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return text; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (AllowEnumerate) Response.Data = ListChildren(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else Respond403(path); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 文件不存在
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>在指定目录下搜索默认文件。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <returns>完整文件路径,当搜索失败时返回 NULL。</returns>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        protected string Default(string directory) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string SearchDefaultFile(string directoryPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var subs = StorageUtility.GetSubFiles(directory); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (subs.Count < 0) return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            subs.Sort(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var names = new Dictionary<string, string>(subs.Count); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var sub in subs) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 获取子文件路径
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var filePaths = StorageUtility.GetSubFiles(directoryPath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (filePaths.Count < 0) return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            filePaths.Sort(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 获取文件名
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var dict = new Dictionary<string, string>(filePaths.Count); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var filePath in filePaths) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var name = Path.GetFileName(sub); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (names.ContainsKey(name)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                names.Add(name, sub); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var name = Path.GetFileName(filePath).ToLower(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (dict.ContainsKey(name)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                dict.Add(name, filePath); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var sub in subs) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 按顺序获取
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            foreach (var defaultFileName in DefaultFileNames) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var name = Path.GetFileName(sub); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var lower = name.ToLower(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (lower == name) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (names.ContainsKey(lower)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                names.Add(lower, sub); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (dict.TryGetValue("index.html", out var physicalPath)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return physicalPath; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (names.ContainsKey("index.html")) return names["index.html"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (names.ContainsKey("index.htm")) return names["index.htm"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (names.ContainsKey("default.html")) return names["default.html"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (names.ContainsKey("default.htm")) return names["default.htm"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region private
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 解析 URL 的路径,获取本地路径。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string MapPath(string urlPath) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Dictionary<string, byte[]> GetWebZip() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var path = GetRoot(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!string.IsNullOrEmpty(urlPath)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var instanceType = GetType(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            lock (WebZips) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                foreach (var split in urlPath.Split('/')) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (WebZips.TryGetValue(instanceType, out var webZip)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return webZip; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var seg = split.ToTrim(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (string.IsNullOrEmpty(seg)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (seg == "." || seg == "..") continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    path = StorageUtility.CombinePath(path, seg); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var dict = LoadWebZip(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (dict != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        var temp = new Dictionary<string, byte[]>(dict.Count); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        foreach (var kvp in dict) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (kvp.Key.IsEmpty()) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            var url = string.Join("/", kvp.Key.Split('/', '\\')); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            url = "/" + url.ToLower(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (temp.ContainsKey(url)) continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            temp.Add(url, kvp.Value); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        dict = temp; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    WebZips.Add(instanceType, dict); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return path; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return null; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Server Side Includes
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string ReadWithSSI(string path, int recursive = 0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        string ServerSideIncludes(string text, int recursive) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (recursive > 10) return ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var input = StorageUtility.ReadFile(path, true); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (input == null || input.LongLength < 1) return ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 尝试解码。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var html = TextUtility.FromBytes(input); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(html)) return ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!AllowSSI) return text; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (recursive > 10) return text; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(text)) return ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 按首尾截取。
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const string left = "<!--"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const string right = "-->"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const string head = "#include virtual="; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var sb = new StringBuilder(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var text = html; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            while (true) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                var offset = text.IndexOf(left); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -288,9 +510,9 @@ namespace Apewer.Web | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    temp = temp.Substring(head.Length); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    temp = temp.Replace("\"", ""); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var subPath = MapPath(temp); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var subText = ReadWithSSI(subPath, recursive + 1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (subText != null && subText.Length > 0) sb.Append(subText); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    var includeText = ReadTextFile(temp, recursive + 1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (includeText != null && includeText.Length > 0) sb.Append(includeText); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -305,6 +527,10 @@ namespace Apewer.Web | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return output; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        #region private
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>列出指定目录的子项。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Json ListChildren(string directory) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -363,7 +589,8 @@ namespace Apewer.Web | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return array; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        static bool IsBlocked(string segment) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// <summary>请求筛选:检查段内容是要被屏蔽。</summary>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        bool IsBlocked(string segment) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (string.IsNullOrEmpty(segment)) return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            var lower = segment.ToLower(); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |