/// <summary>
        /// Static file module handle request and trigged this method
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task HandleRequestAsync(IHttpContext context)
        {
            if (context.IsHandled)
            {
                return;
            }
            string fileName = string.Empty;

            if (context.Request.RawUrl == "/")
            {
                fileName = "index.html";
            }
            else
            {
                fileName = options.ExecutionDirectory;
                foreach (var dir in context.Request.RawUrl.Split('/'))
                {
                    fileName = Path.Combine(fileName, dir.ToLowerInvariant());
                }
            }
            while (fileName.Contains("?") || fileName.Contains("&"))
            {
                var indexOf = fileName.IndexOf('?');
                if (indexOf == -1)
                {
                    indexOf = fileName.IndexOf('&');
                }
                if (indexOf != -1)
                {
                    fileName = fileName.Substring(0, indexOf);
                }
            }
            var contentType = MimeType.Associations.GetValueOrDefault(Path.GetExtension(fileName));

            byte[] bytes = null;
            if (_files.ContainsKey(fileName))
            {
                if (_files.TryGetValue(fileName, out StaticFileItem staticFileItem))
                {
                    bytes = staticFileItem.Data;
                    if (options.CacheActive)
                    {
                        var expire = (staticFileItem.ExpireDate - DateTime.Now).TotalSeconds;
                        context.AddCacheExpire(expire);
                    }
                }
            }
            else
            {
                try
                {
                    if (File.Exists(fileName))
                    {
                        if (contentType.StartsWith("text"))
                        {
                            bytes = Encoding.UTF8.GetBytes(File.ReadAllText(fileName));
                        }
                        else
                        {
                            using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
                            {
                                bytes = new byte[fs.Length];
                                fs.Read(bytes, 0, (int)fs.Length);
                            }
                        }

                        if (options.CacheActive)
                        {
                            _files.TryAdd(fileName, new StaticFileItem(bytes, DateTime.Now.AddSeconds(options.ExpireTime)));
                            var expire = DateTime.Now.AddMinutes(5).Second;
                            context.AddCacheExpire(expire);
                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            if (bytes != null)
            {
                if (options.AllowedMimeTypes.Any(f => f == "*" || f == contentType))
                {
                    if (!contentType.StartsWith("text"))
                    {
                        context.Response.Headers.Add("Content-disposition", "attachment; filename=" + Guid.NewGuid().ToString() + Path.GetExtension(fileName));
                    }
                    context.Response.OutputStream.Write(bytes);
                    context.Response.ContentType = contentType;
                    context.Response.StatusCode  = (int)HttpStatusCode.OK;
                    context.SetHandled();
                }
            }
        }