Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        // 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);
            }
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
 public bool ProcessIfMatch(IWebContext context, out IWebCommandResult result)
 {
     Contract.Requires(context != null);
     throw new System.NotImplementedException();
 }