public void SettingCachingRuleShouldWork() { TimeSpan maxAge = TimeSpan.FromDays(7); cmd.CacheByMaxAge(@"somedir\*", maxAge); routeMatch.AddParameter("path", @"somedir\somepath.png"); const string ExpectedFileName = @"d:\somedir\contents\somedir\somepath.png"; fileSystem.Stub(x => x.DoesFileExist(ExpectedFileName)).Return(true); IFileInformation fileInfo = MockRepository.GenerateStub <IFileInformation>(); fileInfo.LastWriteTime = now.AddDays(-3); fileSystem.Stub(x => x.GetFileInformation(ExpectedFileName)).Return(fileInfo); fileSystem.Stub(x => x.ReadFileAsBytes(ExpectedFileName)).Return(new byte[100]); IWebCommandResult result = cmd.Execute(context, routeMatch); FileResult fileResult = (FileResult)result; CachingByMaxAgePolicy maxAgePolicy = (CachingByMaxAgePolicy)fileResult.CachingPolicy; Assert.AreEqual(maxAge, maxAgePolicy.MaxAge); context.RequestHeaders.Add(HttpConsts.HeaderIfModifiedSince, fileInfo.LastWriteTime.ToRfc2822DateTime()); result.Apply(context); Assert.AreEqual((int)HttpStatusCode.NotModified, context.StatusCode); }
public void TestCachingByETag() { log.Debug("TestCachingByETag"); TimeSpan maxAge = TimeSpan.FromDays(30); cmd.CacheByETag( @"somedir\*", maxAge, () => new Tuple <string, DateTime?>("xyz", new DateTime(2016, 01, 19, 10, 22, 0))); routeMatch.AddParameter("path", @"somedir\somepath.png"); const string ExpectedFileName = @"d:\somedir\contents\somedir\somepath.png"; fileSystem.Stub(x => x.DoesFileExist(ExpectedFileName)).Return(true); IWebCommandResult result = cmd.Execute(context, routeMatch); FileResult fileResult = (FileResult)result; CachingByETagPolicy cachingPolicy = (CachingByETagPolicy)fileResult.CachingPolicy; Assert.AreEqual(maxAge, cachingPolicy.MaxAge); context.RequestHeaders.Add(HttpConsts.HeaderIfNoneMatch, "xyz"); result.Apply(context); Assert.AreEqual((int)HttpStatusCode.NotModified, context.StatusCode); }
public void EnsurePathsOutsideContentDirAreForbidden() { routeMatch.AddParameter("path", @"..\forbidden\web.config"); IWebCommandResult result = cmd.Execute(context, routeMatch); HttpStatusResult fileResult = (HttpStatusResult)result; Assert.AreEqual((int)HttpStatusCode.Forbidden, fileResult.StatusCode); }
public void EnsureAbsolutePathsAreDisabled() { routeMatch.AddParameter("path", @"d:/somedir/somepath.png"); IWebCommandResult result = cmd.Execute(context, routeMatch); HttpStatusResult fileResult = (HttpStatusResult)result; Assert.AreEqual((int)HttpStatusCode.BadRequest, fileResult.StatusCode); }
public void FileDoesNotExist() { routeMatch.AddParameter("path", @"somedir/somepath.png"); IWebCommandResult result = cmd.Execute(context, routeMatch); HttpStatusResult fileResult = (HttpStatusResult)result; Assert.AreEqual((int)HttpStatusCode.NotFound, fileResult.StatusCode); }
public bool ProcessIfMatch(IWebContext context, out IWebCommandResult result) { //log.DebugFormat("ApplicationUrl={0}, Url={1}, RawUrl={2}, ApplicationPath={3}", context.ApplicationUrl, context.Url, context.RawUrl, context.ApplicationPath); result = null; IWebServerConfiguration configuration = context.Configuration; if (context.IsSecureConnection) { return(false); } if (configuration.HttpsMode == HttpsMode.AllowBoth) { return(false); } if (configuration.HttpsMode == HttpsMode.RequireHttpsExceptLocal) { if (context.IsRequestLocal) { return(false); } } HttpStatusResult httpStatusResult = new HttpStatusResult(HttpStatusCode.MovedPermanently); UriBuilder uriBuilder = new UriBuilder(context.Url); uriBuilder.Scheme = "https"; if (configuration.HttpsPort.HasValue) { uriBuilder.Port = configuration.HttpsPort.Value; } else { uriBuilder.Port = -1; } string destinationUrl = uriBuilder.ToString(); httpStatusResult.AddHeader(HttpConsts.HeaderLocation, destinationUrl); if (log.IsDebugEnabled) { log.DebugFormat("Redirecting request '{0}' to '{1}'", context.ApplicationUrl, destinationUrl); } result = httpStatusResult; return(true); }
public void NoCachingIsDoneByDefault() { routeMatch.AddParameter("path", @"somedir/somepath.png"); const string ExpectedFileName = @"d:\somedir\contents\somedir\somepath.png"; fileSystem.Stub(x => x.DoesFileExist(ExpectedFileName)).Return(true); IWebCommandResult result = cmd.Execute(context, routeMatch); FileResult fileResult = (FileResult)result; Assert.IsInstanceOf <NoCachingPolicy>(fileResult.CachingPolicy); }
public void FetchFile() { routeMatch.AddParameter("path", @"somedir/somepath.png"); const string ExpectedFileName = @"d:\somedir\contents\somedir\somepath.png"; fileSystem.Stub(x => x.DoesFileExist(ExpectedFileName)).Return(true); IWebCommandResult result = cmd.Execute(context, routeMatch); FileResult fileResult = (FileResult)result; Assert.AreEqual(ExpectedFileName, fileResult.FileName); }
public void SettingCachingRuleDoesNotMatch() { TimeSpan maxAge = TimeSpan.FromDays(7); cmd.CacheByMaxAge(@"somedir2\*", maxAge); routeMatch.AddParameter("path", @"somedir\somepath.png"); const string ExpectedFileName = @"d:\somedir\contents\somedir\somepath.png"; fileSystem.Stub(x => x.DoesFileExist(ExpectedFileName)).Return(true); IWebCommandResult result = cmd.Execute(context, routeMatch); FileResult fileResult = (FileResult)result; Assert.IsInstanceOf <NoCachingPolicy>(fileResult.CachingPolicy); }
// ReSharper disable once InconsistentNaming private static void Application_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext httpContext = application.Context; try { SyborgHttpModuleAppHost appHost = (SyborgHttpModuleAppHost)application.Application[KeyAppHost]; if (appHost.WebServerConfiguration.SimulatedResponseLag > TimeSpan.Zero) { Thread.Sleep(appHost.WebServerConfiguration.SimulatedResponseLag); } IWebContext context = appHost.CreateWebContext(httpContext); //if (log.IsDebugEnabled) // log.DebugFormat("Request: {0}", context.RawUrl); // this is to prevent protocol violation error if (context.HttpMethod == "HEAD") { context.CloseResponse(); return; } IWebCommandResult webCommandResult = null; try { foreach (IWebRequestRoute route in appHost.Routes) { if (route.ProcessIfMatch(context, out webCommandResult)) { break; } } } catch (Exception ex) { log.FatalFormat("Web request failed when routing: {0}", ex); webCommandResult = new HttpStatusResult( HttpStatusCode.InternalServerError, "Ooops... an error occurred during the processing of your request. If this error persists, please contact our site administrator at [email protected]. Thank you!"); } if (webCommandResult == null) { webCommandResult = new HttpStatusResult(HttpStatusCode.BadRequest); } webCommandResult.Apply(context); if (!context.IsResponseClosed) { log.ErrorFormat( CultureInfo.InvariantCulture, "BUG: the response was not closed properly (thread {0}, URL={1})!", Thread.CurrentThread.ManagedThreadId, context.RawUrl); context.StatusCode = (int)HttpStatusCode.InternalServerError; context.CloseResponse(); } LogTraffic(context); } catch (HttpListenerException ex) { // An operation was attempted on a nonexistent network connection if ((uint)ex.ErrorCode == 0x80004005) { //log.WarnFormat("HttpListenerException: {0:X}", ex.ErrorCode); // ignore this } else { log.Warn("HttpListenerException", ex); } } catch (ObjectDisposedException ex) { log.Warn("ObjectDisposedException", ex); } catch (Exception ex) { log.FatalFormat("Web request failed when applying the result: {0}", ex); } }
// ReSharper disable once CyclomaticComplexity private void WebRequestCallback(IAsyncResult result) { if (log.IsDebugEnabled) { log.DebugFormat("WebRequestCallback (thread {0})", Thread.CurrentThread.ManagedThreadId); } try { if (!httpListener.IsListening) { log.Info("Received web request, but HTTP listener is not listening"); return; } if (configuration.SimulatedResponseLag > TimeSpan.Zero) { Thread.Sleep(configuration.SimulatedResponseLag); } HttpListenerContext listenerContext = httpListener.EndGetContext(result); Contract.Assume(listenerContext != null); IWebContext context = new HttpListenerWebContext( listenerContext, FullWebServerUrl, applicationPath, fileSystem, applicationInfo, timeService, configuration, viewRenderingEngine, fileMimeTypesMap); OnRequestReceived(context); foreach (IWebPolicy policy in policies) { context.AddPolicy(policy); } httpListener.BeginGetContext(WebRequestCallback, httpListener); if (log.IsDebugEnabled) { log.DebugFormat("Request: {0} {1}", context.HttpMethod, context.RawUrl); } // this is to prevent protocol violation error if (context.HttpMethod == "HEAD") { context.CloseResponse(); return; } IWebCommandResult webCommandResult = null; try { foreach (IWebRequestRoute route in routes) { if (route.ProcessIfMatch(context, out webCommandResult)) { break; } } } catch (KeyNotFoundException ex) { log.InfoFormat("Error processing request: {0}", ex); webCommandResult = new HttpStatusResult(HttpStatusCode.NotFound); } catch (Exception ex) { webCommandResult = new HttpStatusResult(HttpStatusCode.InternalServerError); log.Error("InternalServerError - processing routes", ex); } if (webCommandResult == null) { webCommandResult = new HttpStatusResult(HttpStatusCode.BadRequest); } try { webCommandResult.Apply(context); } catch (Exception ex) { webCommandResult = new HttpStatusResult(HttpStatusCode.InternalServerError); log.Error("InternalServerError - apply web command result", ex); webCommandResult.Apply(context); } if (!context.IsResponseClosed) { log.ErrorFormat("BUG: the response was not closed properly (thread {0}, URL={1})!", Thread.CurrentThread.ManagedThreadId, context.RawUrl); context.StatusCode = (int)HttpStatusCode.InternalServerError; context.CloseResponse(); } } catch (HttpListenerException ex) { // An operation was attempted on a nonexistent network connection if ((uint)ex.ErrorCode == 0x80004005) { //log.WarnFormat("HttpListenerException: {0:X}", ex.ErrorCode); // ignore this } else { log.Warn("HttpListenerException", ex); } } catch (ObjectDisposedException ex) { log.Warn("ObjectDisposedException", ex); } catch (Exception ex) { log.Fatal("Web request processing thread failed", ex); webServerController.SignalToAbort("Web request processing thread failed"); } if (log.IsDebugEnabled) { log.DebugFormat("Finished WebRequestCallback (thread {0})", Thread.CurrentThread.ManagedThreadId); } }
public bool ProcessIfMatch(IWebContext context, out IWebCommandResult result) { result = null; if (context.HttpMethod != httpMethod) { return(false); } UriBuilder urlBuilder = new UriBuilder(context.Url); // ensure the URL path is decoded string urlPath = HttpUtility.UrlDecode(urlBuilder.Path); if (urlPath == null) { throw new InvalidOperationException("Cannot process the URL '{0}'".Fmt(context.Url)); } string applicationPath = context.ApplicationPath; if (applicationPath != null) { if (!urlPath.StartsWith(applicationPath, StringComparison.OrdinalIgnoreCase)) { return(false); } bool endsWithSlash = applicationPath.EndsWith("/", StringComparison.Ordinal); int startIndex = applicationPath.Length - (endsWithSlash ? 1 : 0); if (startIndex > urlPath.Length) { return(false); } urlPath = urlPath.Substring(startIndex); } if (urlPath.Length > 1) { int endCharsCutOff = 0; if (urlPath.EndsWith("/", StringComparison.OrdinalIgnoreCase)) { endCharsCutOff++; } urlPath = urlPath.Substring(1, urlPath.Length - (1 + endCharsCutOff)); } else { if (urlPath.Length >= 1 && urlPath[0] != '/') { throw new InvalidOperationException("URL path is invalid: '{0}'".Fmt(urlPath)); } urlPath = string.Empty; } Match match = routeRegex.Match(urlPath); if (!match.Success) { return(false); } if (log.IsDebugEnabled) { log.DebugFormat("Executing web command {0}", command); } WebRequestRouteMatch routeMatch = WebRequestRouteMatch.FromRegexMatch(routeRegex, match); result = command.Execute(context, routeMatch); return(true); }
public bool ProcessIfMatch(IWebContext context, out IWebCommandResult result) { Contract.Requires(context != null); throw new System.NotImplementedException(); }