private Stream getUrlStream(String url, out ResourceWebResponse response)
 {
     Uri uri = new Uri(url);
     response = null;
     try { response = WebRequest.Create(uri).GetResponse() as ResourceWebResponse; }
     catch { }
     var stream = response?.GetResponseStream();
     return stream;
 }
 private Task handleResource(IOwinContext context, Stream stream, ResourceWebResponse resourceResponse)
 {
     return Task.Factory.StartNew(() =>
     {
         var req = context.Request;
         var rep = context.Response;
         //验证缓存有效
         {
             //===================
             //先验证最后修改时间
             //===================
             var resourceLastModified = resourceResponse.LastModified;
             //最后修改时间判断部分
             var clientLastModified = req.Headers.Get("If-Modified-Since");
             if (clientLastModified != null)
             {
                 if (clientLastModified == resourceLastModified.ToString("R"))
                 {
                     rep.StatusCode = 304;
                     return;
                 }
             }
             //===================
             //然后验证ETag
             //===================
             //ETag设置判断部分
             String serverETag = null;
             if (useMd5ETag)
                 serverETag = HashUtils.ComputeETagByMd5(stream);
             else
                 serverETag = resourceResponse.LastModified.Ticks.ToString();
             var clientETag = req.Headers.Get("If-None-Match");
             //如果客户端的ETag值与服务端相同,则返回304,表示资源未修改
             if (serverETag == clientETag)
             {
                 rep.StatusCode = 304;
                 return;
             }
             rep.ETag = serverETag;
             stream.Position = 0;
         }
         //设置MIME类型
         var mime = MimeUtils.GetMime(resourceResponse.Uri.LocalPath);
         if (mime != null)
             rep.ContentType = mime;
         rep.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(resourceExpires));
         rep.Headers["Cache-Control"] = $"max-age={resourceExpires}";
         rep.Headers["Last-Modified"] = resourceResponse.LastModified.ToUniversalTime().ToString("R");
         Output(context, stream);
     });
 }
 private Task handleResource(IOwinContext context, Stream stream, ResourceWebResponse resourceResponse, double expires)
 {
     var req = context.Request;
     var rep = context.Response;
     //验证缓存有效
     {
         //===================
         //先验证最后修改时间
         //===================
         var resourceLastModified = resourceResponse.LastModified;
         //最后修改时间判断部分
         var clientLastModified = req.Headers.Get("If-Modified-Since");
         if (clientLastModified != null)
         {
             if (clientLastModified == resourceLastModified.ToString("R"))
             {
                 rep.StatusCode = 304;
                 return Task.Run(() => stream.Dispose());
             }
         }
         //===================
         //然后验证ETag
         //===================
         //ETag设置判断部分
         String serverETag = null;
         if (UseMd5ETag)
             serverETag = HashUtils.ComputeETagByMd5(stream);
         else
             serverETag = resourceResponse.LastModified.Ticks.ToString();
         var clientETag = req.Headers.Get("If-None-Match");
         //如果客户端的ETag值与服务端相同,则返回304,表示资源未修改
         if (serverETag == clientETag)
         {
             rep.StatusCode = 304;
             return Task.Run(() => stream.Dispose());
         }
         rep.ETag = serverETag;
         stream.Position = 0;
     }
     rep.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(expires));
     rep.Headers["Cache-Control"] = $"max-age={expires}";
     rep.Headers["Last-Modified"] = resourceResponse.LastModified.ToUniversalTime().ToString("R");
     return context.Output(stream, true, EnableCompress, resourceResponse.Uri.LocalPath);
 }