/// <summary> /// Handle the request. /// </summary> /// <param name="context">HTTP context</param> /// <returns><see cref="ModuleResult.Stop"/> will stop all processing except <see cref="IHttpModule.EndRequest"/>.</returns> /// <remarks>Invoked in turn for all modules unless you return <see cref="ModuleResult.Stop"/>.</remarks> public ModuleResult HandleRequest(IHttpContext context) { // only handle GET and HEAD if (!context.Request.HttpMethod.ToUpper().Equals("GET") && !context.Request.HttpMethod.ToUpper().Equals("HEAD")) return ModuleResult.Continue; // serve a directory if (AllowListing) { if (TryGenerateDirectoryPage(context)) return ModuleResult.Stop; } var header = context.Request.Headers["If-Modified-Since"]; var time = header != null ? DateUtility.Parse(header) : DateTime.MinValue; var fileContext = new FileContext(context.Request, time); _fileService.GetFile(fileContext); if (!fileContext.IsFound) return ModuleResult.Continue; if (!fileContext.IsModified) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.StatusDescription = "Was last modified " + fileContext.LastModifiedAtUtc.ToString("R"); return ModuleResult.Stop; } string mimeType = MimeTypeProvider.Instance.Get(fileContext.Filename); if (mimeType == null) { context.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; context.Response.StatusDescription = string.Concat("File type '", Path.GetExtension(fileContext.Filename),"' is not supported."); return ModuleResult.Stop; } context.Response.AddHeader("Last-Modified", fileContext.LastModifiedAtUtc.ToString("R")); context.Response.AddHeader("Accept-Ranges", "bytes"); context.Response.AddHeader("Content-Disposition", "inline;filename=\"" + Path.GetFileName(fileContext.Filename) + "\""); context.Response.ContentType = mimeType; context.Response.ContentLength = (int)fileContext.FileStream.Length; context.Response.Body = fileContext.FileStream; Logger.WriteDebug(this, "Sent File: " + fileContext.Filename); // Do not include a body when the client only want's to get content information. if (context.Request.HttpMethod.ToUpper().Equals("HEAD") && context.Response.Body != null) { context.Response.Body.Dispose(); context.Response.Body = null; } return ModuleResult.Stop; }
/// <summary> /// Execute the response result. /// </summary> /// <param name="context">HTTP controller context</param> /// <remarks>Invoked by <see cref="ControllerFactory"/> to process the response.</remarks> public override void ExecuteResult(IControllerContext context) { //Logger.WriteDebug(this, "Pipeline => ExecuteResult"); if (context == null) { throw new ArgumentNullException("context"); } // only handle GET and HEAD if (!context.HttpContext.Request.HttpMethod.ToUpper().Equals("GET") && !context.HttpContext.Request.HttpMethod.ToUpper().Equals("HEAD")) return; var header = context.HttpContext.Request.Headers["If-Modified-Since"]; // TODO: Build reliable date parser var time = DateTime.MinValue; //var time = header != null // ? ParseUtility.TryParseDateTime(header) // : DateTime.MinValue; var fileContext = new FileContext(context.HttpContext.Request, time); _fileService.GetFile(fileContext,_fullFilePath); if (!fileContext.IsFound) return; if (!fileContext.IsModified) { context.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified; context.HttpContext.Response.StatusDescription = "Was last modified " + fileContext.LastModifiedAtUtc.ToString("R"); return; } var mimeType = MimeTypeProvider.Instance.Get(fileContext.Filename); if (mimeType == null) { context.HttpContext.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; context.HttpContext.Response.StatusDescription = string.Concat("File type '", Path.GetExtension(fileContext.Filename), "' is not supported."); return; } context.HttpContext.Response.AddHeader("Last-Modified", fileContext.LastModifiedAtUtc.ToString("R")); context.HttpContext.Response.AddHeader("Accept-Ranges", "bytes"); context.HttpContext.Response.AddHeader("Content-Disposition", "inline;filename=\"" + Path.GetFileName(fileContext.Filename) + "\""); context.HttpContext.Response.ContentType = mimeType; context.HttpContext.Response.ContentLength = (int)fileContext.FileStream.Length; context.HttpContext.Response.Body = fileContext.FileStream; // Do not include a body when the client only want's to get content information. if (context.HttpContext.Request.HttpMethod.ToUpper().Equals("HEAD") && context.HttpContext.Response.Body != null) { context.HttpContext.Response.Body.Dispose(); context.HttpContext.Response.Body = null; } }
/// <summary> /// Get a file /// </summary> /// <param name="context">Context used to locate and return files</param> public virtual bool GetFile(FileContext context) { var fullPath = GetFullPath(context.Request.UriRewrite); return GetFile(context, fullPath); }
/// <summary> /// Get a file /// </summary> /// <param name="context">Context used to locate and return files</param> /// <param name="fullPath">Full path used to locate files</param> public virtual bool GetFile(FileContext context, string fullPath) { if (fullPath == null || !File.Exists(fullPath)) return false; FileInfo fi = new FileInfo(fullPath); var date = fi.LastWriteTimeUtc; // browser ignores second fractions date = date.AddTicks(-(date.Ticks % TimeSpan.TicksPerSecond)); if (date <= context.BrowserCacheDate) { context.SetNotModified(fullPath, date); return true; } try { var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); context.SetFile(fullPath, stream, date); return true; } catch { return false; } }
/// <summary> /// Execute the response result. /// </summary> /// <param name="context">HTTP controller context</param> /// <remarks>Invoked by <see cref="ControllerFactory"/> to process the response.</remarks> public override void ExecuteResult(IControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } // only handle GET and HEAD if (!context.HttpContext.Request.HttpMethod.ToUpper().Equals("GET") && !context.HttpContext.Request.HttpMethod.ToUpper().Equals("HEAD")) return; var header = context.HttpContext.Request.Headers["If-Modified-Since"]; // TODO: Build reliable date parser var time = DateTime.MinValue; //var time = header != null // ? ParseUtility.TryParseDateTime(header) // : DateTime.MinValue; var fileContext = new FileContext(context.HttpContext.Request, time); string fileNamePath = string.Concat(@"\winfs\", Constants.HTTP_WEB_ROOT_FOLDER, @"\", Constants.HTTP_WEB_VIEWS_FOLDER, @"\", context.ControllerName.Replace("Controller", String.Empty), @"\", context.ActionName, @".html"); _fileService.GetFile(fileContext, fileNamePath); if (!fileContext.IsFound) { context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.HttpContext.Response.StatusDescription = string.Concat("Failed to find view '", fileContext.Filename, "."); return; } var mimeType = MimeTypeProvider.Instance.Get(fileContext.Filename); if (mimeType == null || mimeType != "text/html") { context.HttpContext.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; context.HttpContext.Response.StatusDescription = string.Concat("File type '", Path.GetExtension(fileContext.Filename), "' is not supported."); return; } context.HttpContext.Response.AddHeader("Last-Modified", fileContext.LastModifiedAtUtc.ToString("R")); context.HttpContext.Response.AddHeader("Accept-Ranges", "bytes"); context.HttpContext.Response.AddHeader("Content-Disposition", "inline;filename=\"" + Path.GetFileName(fileContext.Filename) + "\""); context.HttpContext.Response.ContentType = mimeType; // Parse tokens from file content using (StreamReader sr = new StreamReader(fileContext.FileStream)) { TokenEngine content = new TokenEngine(sr.ReadToEnd(), context.ViewData); MemoryStream body = new MemoryStream(Encoding.UTF8.GetBytes(content.ToString())); context.HttpContext.Response.Body = body; context.HttpContext.Response.ContentLength = (int)body.Length; } // Do not include a body when the client only want's to get content information. if (context.HttpContext.Request.HttpMethod.ToUpper().Equals("HEAD") && context.HttpContext.Response.Body != null) { context.HttpContext.Response.Body.Dispose(); context.HttpContext.Response.Body = null; } }