예제 #1
0
		async public Task FilterAsync(HttpRequest Request, HttpResponse Response)
		{
			var FilePath = Request.Url.Path;
			if (Path.GetExtension(FilePath) == "")
			{
				if (Directory.Exists(FilePath))
				{
					FilePath = Url.Normalize(FilePath + "/index.html");
				}
			}

			//var CacheKey = FilePath.ToLowerInvariant();
			//var CacheKey = FilePath;
			var CachedResult = await Cache.GetAsync(FilePath, async () =>
			{
				var Extension = Path.GetExtension(FilePath);
				if (ExtensionHandlersAsync.ContainsKey(Extension))
				{
					try
					{
						return await ExtensionHandlersAsync[Extension](new HandlerStruct(this)
						{
							FileSystem = VirtualFileSystem,
							FilePath = FilePath,
						});
					}
					catch (FileNotFoundException)
					{
						throw (new HttpException(HttpCode.NOT_FOUND_404));
					}
				}

				if (Cache.Enabled)
				{
					await Console.Out.WriteLineAsync(String.Format("Caching '{0}'", FilePath));
				}

				var FileInfo = await VirtualFileSystem.GetFileInfoAsync(FilePath);

				if (FileInfo.Exists)
				{
					bool ShouldCacheInMemory = FileInfo.Length <= CacheSizeThresold;
					string ETag = null;
					byte[] Data = null;

					if (ShouldCacheInMemory)
					{
						Data = await VirtualFileSystem.ReadAsBytesAsync(FilePath);
						ETag = BitConverter.ToString(MD5.Create().ComputeHash(Data));
					}

					return new ResultStruct()
					{
						RealFilePath = FilePath,
						ContentType = MimeType.GetFromPath(FilePath),
						FileInfo = FileInfo,
						ETag = ETag,
						Data = Data,
						Exists = true,
					};
				}
				else
				{
					throw (new HttpException(HttpCode.NOT_FOUND_404));
				}
			});

			Response.Headers["Content-Type"] = CachedResult.ContentType;
			if (CachedResult.ETag != null)
			{
				Response.Headers["ETag"] = CachedResult.ETag;
			}
			Response.Headers["Date"] = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
			Response.Headers["Last-Modified"] = CachedResult.FileInfo.LastWriteTimeUtc.ToString("R", CultureInfo.InvariantCulture);
			Response.Headers["Cache-Control"] = "max-age=2419200, private";
			Response.Headers["Expires"] = "Wed, 11 Apr 2022 18:23:41 GMT";

			// Check ETag
			if (Request.Headers["If-None-Match"] != "")
			{
				if (Request.Headers["If-None-Match"] == CachedResult.ETag)
				{
					throw(new HttpException(HttpCode.NOT_MODIFIED_304));
				}
			}

			// Check Last-Modified
			if (Request.Headers["If-Modified-Since"] != "")
			{
				var RequestIfModifiedSince = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "R", CultureInfo.InvariantCulture);

				if (RequestIfModifiedSince == CachedResult.FileInfo.LastWriteTimeUtc)
				{
					throw(new HttpException(HttpCode.NOT_MODIFIED_304));
				}
			}

			Response.Buffering = true;
			Response.ChunkedTransferEncoding = false;

			/*
			Cache-Control:max-age=2419200, private
			Connection:keep-alive
			Date:Wed, 14 Mar 2012 14:52:54 GMT
			Expires:Wed, 11 Apr 2012 14:52:54 GMT
			Last-Modified:Wed, 11 Jan 2012 13:52:46 GMT
			*/

			Response.Headers["Content-Length"] = CachedResult.FileInfo.Length.ToString();

			// Cached byte[]
			if (CachedResult.Data != null)
			{
				await Response.WriteAsync(CachedResult.Data);
			}
			// No cached byte[], stream the file
			else
			{
				Response.Buffering = false;
				//Response.ChunkedTransferEncoding = true;
				await Response.StreamFileASync(CachedResult.RealFilePath);
			}
		}