/// <summary> /// If validation with the DEA is successful, the HTTP request is served. /// Otherwise, the same HTTP response from the DEA is served as response to /// the HTTP request. /// </summary> /// <param name="listenerContext">Http context to respond to.</param> private void ServeHttp(object listenerContext) { try { HttpListenerContext context = (HttpListenerContext)listenerContext; Uri uri = context.Request.Url; PathLookupResponse response = this.deaClient.LookupPath(uri); if (!string.IsNullOrWhiteSpace(response.Error)) { Logger.Warning(Strings.ErrorInLookupPath, response.Error); DirectoryServer.WriteServerError(Strings.WinDEADidNotRespondProperly, context); } else { var queryString = string.Join(string.Empty, uri.PathAndQuery.Split('?').Skip(1)); NameValueCollection queryStrings = System.Web.HttpUtility.ParseQueryString(queryString); bool tail = queryStrings.AllKeys.Select(key => queryStrings.GetValues(key).Contains("tail")).Any(v => v); Logger.Debug("Directory Server file request is: {0}; path is {1}", uri, queryStrings["path"]); this.ListPath(response.Path, tail, context); } } catch (Exception ex) { Logger.Error("Directory Server - there was an error serving http: {0}", ex.ToString()); } }
/// <summary> /// Looks up the path in the DEA. /// </summary> /// <param name="path">The path to lookup.</param> /// <returns> /// A PathLookupResponse containing the response from the DEA. /// </returns> public PathLookupResponse LookupPath(Uri path) { if (path == null) { throw new ArgumentNullException("path"); } PathLookupResponse response = new PathLookupResponse(); response.Error = string.Empty; NameValueCollection queryStrings = System.Web.HttpUtility.ParseQueryString(path.Query); string actualPath = HttpUtility.UrlDecode(queryStrings["path"]); switch (path.Segments[1].Replace("/", string.Empty)) { case "instance_paths": { this.droplets.ForEach(delegate(DropletInstance droplet) { if (droplet.Properties.InstanceId == path.Segments[2].Replace("/", string.Empty)) { if (DEAUtilities.VerifyHmacedUri(path.ToString(), this.directoryServerHmacKey, new string[] { "path", "timestamp" })) { string physicalPath = Path.GetFullPath((new Uri(Path.Combine(droplet.Properties.Directory, ".\\" + actualPath))).LocalPath); ; if (physicalPath.StartsWith(droplet.Properties.Directory + Path.DirectorySeparatorChar)) { response.Path = Path.GetFullPath(physicalPath); } else { response.Error = "Cannot access path"; } } else { response.Error = "Invalid HMAC"; } if (!DEAUtilities.CheckUrlAge(path.ToString())) { response.Error = "URL expired"; } } }); break; } case "staging_tasks": { this.stagingTaskRegistry.ForEach(delegate(StagingInstance instance) { if (instance.Properties.TaskId == path.Segments[2].Replace("/", string.Empty)) { if (DEAUtilities.VerifyHmacedUri(path.ToString(), this.directoryServerHmacKey, new string[] { "path", "timestamp" })) { response.Path = instance.Properties.TaskLog; } else { response.Error = "Invalid HMAC"; } if (!DEAUtilities.CheckUrlAge(path.ToString())) { response.Error = "URL expired"; } } }); break; } default: { break; } } if (response.Path == null && string.IsNullOrEmpty(response.Error)) { response.Error = "Staging task not found"; } return response; }