예제 #1
0
		// finds and matches a tracker (this a or sub-tracker in varyby cases) for a HttpRequest
		public Tracker FindTrackerForRequest(HttpRequest request)
		{
			// path
			if (String.Compare(_path, request.FilePath, StringComparison.OrdinalIgnoreCase) != 0)
			{
				return null;
			}

			// verbs
			bool verbMatchFound = String.Compare(_verbs[0], request.HttpMethod, StringComparison.OrdinalIgnoreCase) == 0;

			if (!verbMatchFound && _verbs.Length > 1)
			{
				for (int i = 1; i < _verbs.Length; i++)
				{
					if (String.Compare(_verbs[i], request.HttpMethod, StringComparison.OrdinalIgnoreCase) == 0)
					{
						verbMatchFound = true;
						break;
					}
				}
			}

			if (!verbMatchFound)
			{
				return null;
			}

			// path info
			if (_emptyPathInfoOnly && !string.IsNullOrEmpty(request.PathInfo))
			{
				return null;
			}

			// query string
			if (_emptyQueryStringOnly && request.QueryString.Count > 0)
			{
				return null;
			}

			// in non-vary-by case return this tracker
			if (_varyBy == null || _varyBy.Length == 0)
			{
				return this;
			}

			// get the child tracker corresponding to vary-by key for this request
			Tracker childTracker = null;
			string varyByKey = CalculateVaryByKey(_varyBy, request);

			lock (_varyByTrackers)
			{
				if (!_varyByTrackers.TryGetValue(varyByKey, out childTracker))
				{
					// create a new child tracker if not exceeding the limit already
					if (_varyByTrackers.Count < HttpModule.OutputCache.VaryByLimit)
					{
						childTracker = new Tracker(this, varyByKey);
						_varyByTrackers.Add(varyByKey, childTracker);
					}
				}
			}

			return childTracker;
		}
예제 #2
0
		// private ctor to create a child tracker for a specific vary-by value
		Tracker(Tracker parent, string varyById)
		{
			_parent = parent;
			_path = parent._path;
			_duration = parent._duration;
			_verbs = parent._verbs;
			_varyBy = parent._varyBy;
			_serveFromMemory = parent._serveFromMemory;
			_varyById = varyById;
			_filenamePrefix = string.Format("{0}_q_{1:x8}", parent._filenamePrefix, varyById.GetHashCode());

			_capturingEvent = new ManualResetEvent(true);
			_varyByTrackers = null; // no need for sub-sub-trackers
		}
예제 #3
0
		void OnResolveRequestCache(object sender, EventArgs e)
		{
			// start clean
			_trackerCapturingResponse = null;

			Tracker tracker = HttpModule.OutputCache.Lookup(_app.Context);

			if (tracker == null)
			{
				// this request is not subject to cache
				return;
			}

			// try to send response or start capture
			// (use 'finally' because starting capture would lock)
			try { }
			finally
			{
				if (tracker.TrySendResponseOrStartResponseCapture(_app.Response))
				{
					// successfully sent current response
					_app.CompleteRequest();
				}
				else
				{
					// started capturing
					_trackerCapturingResponse = tracker;
				}
			}
		}
예제 #4
0
		void OnEndRequest(object sender, EventArgs e)
		{
			if (_trackerCapturingResponse != null)
			{
				// if still capturing, abandon the process
				try
				{
					_trackerCapturingResponse.CancelCapture(_app.Response);
				}
				finally
				{
					_trackerCapturingResponse = null;
				}
			}
		}
예제 #5
0
		void OnUpdateRequestCache(object sender, EventArgs e)
		{
			if (_trackerCapturingResponse != null)
			{
				// if capturing, finish the capture and save the file
				_trackerCapturingResponse.FinishCaptureAndSaveResponse(_app.Response);
				_trackerCapturingResponse = null;
			}
		}
예제 #6
0
		bool Startup()
		{
			DiskOutputCacheSettingsSection config = (DiskOutputCacheSettingsSection)
								WebConfigurationManager.GetWebApplicationSection("diskOutputCacheSettings");

			if (config == null)
			{
				// no config - the list of URLs is empty
				return false;
			}

			if (string.IsNullOrEmpty(config.Location))
			{
				// the default location is in temporary asp.net files
				_location = Path.Combine(HttpRuntime.CodegenDir, "DiskOutputCache");

				if (!Directory.Exists(_location))
				{
					Directory.CreateDirectory(_location);
				}
			}
			else
			{
				_location = config.Location;

				if (!Directory.Exists(_location))
				{
					throw new InvalidDataException(string.Format("Invalid location '{0}'", _location));
				}
			}

			_varyByLimit = config.VaryByLimitPerUrl;
			_fileValidationDelay = config.FileValidationDelay;

			foreach (CachedUrlsElement e in config.CachedUrls)
			{
				string path = e.Path;

				if (!VirtualPathUtility.IsAppRelative(path) && !VirtualPathUtility.IsAbsolute(path))
				{
					throw new InvalidDataException(string.Format("Invalid path '{0}', absolute or app-relative path expected", path));
				}

				path = VirtualPathUtility.ToAbsolute(path);
				// create file path prefix for this path
				string relPathPrefix = VirtualPathUtility.ToAppRelative(path);
				if (relPathPrefix.StartsWith("~/"))
				{
					relPathPrefix = relPathPrefix.Substring(2);
				}
				relPathPrefix = relPathPrefix.Replace('.', '_');
				relPathPrefix = relPathPrefix.Replace('/', '_');

				// list of verbs
				string[] verbs = ParseStringList(e.Verbs);
				if (verbs.Length == 0)
				{
					throw new InvalidDataException(string.Format("Invalid list of verbs '{0}'", e.Verbs));
				}

				// vary-by
				string[] varyBy = ParseStringList(e.VaryBy);

				// remember the tracker object
				_trackers[path] = new Tracker(path, Path.Combine(_location, relPathPrefix), e.Duration,
						verbs, varyBy, e.EmptyQueryStringOnly, e.EmptyPathInfoOnly, e.ServeFromMemory);

			}

			return true;
		}