/// <summary>Converts string values to given collection.</summary> /// <param name="converterProvider">The converter provider.</param> /// <param name="values">The values.</param> /// <param name="collectionType">The collection type.</param> /// <param name="request">The request.</param> /// <returns>Instance of the <paramref name="collectionType" />.</returns> public static object ConvertToCollection(this IConverterProvider converterProvider, IEnumerable<string> values, Type collectionType, IRequestInfo request = null) { if (values == null) { return null; } if (collectionType == null) { throw new ArgumentNullException("collectionType"); } var itemType = collectionType.GetItemType(); bool success; var result = ConvertUsingTypeConverters(values, itemType, out success); if ((success) || (request == null)) { return result.MakeInstance(collectionType, itemType); } if (converterProvider == null) { throw new ArgumentNullException("converterProvider"); } return ConvertUsingCustomConverters(converterProvider, request, values, itemType).MakeInstance(collectionType, itemType); }
public ApiRequest(IRequestInfo requestinfo, CollectionSettings currentCollectionSettings, Book.Book currentBook) { _requestInfo = requestinfo; CurrentCollectionSettings = currentCollectionSettings; CurrentBook = currentBook; Parameters = requestinfo.GetQueryParameters(); }
/// <summary>Converts string to given type.</summary> /// <param name="converterProvider">The converter provider.</param> /// <param name="value">The value.</param> /// <param name="type">The target type.</param> /// <param name="request">The request.</param> /// <returns>Instance of the <paramref name="type" />.</returns> public static object ConvertTo(this IConverterProvider converterProvider, string value, Type type, IRequestInfo request = null) { if (type == null) { throw new ArgumentNullException("type"); } if (value == null) { return (type.IsValueType ? Activator.CreateInstance(type) : null); } bool success; object result = ConvertUsingTypeConverters(value, type, out success); if ((success) || (request == null)) { return result; } if (converterProvider == null) { throw new ArgumentNullException("converterProvider"); } return ConvertUsingCustomConverters(converterProvider, request, value, type); }
public static bool Handle(EndpointRegistration endpointRegistration, IRequestInfo info, CollectionSettings collectionSettings, Book.Book currentBook) { var request = new ApiRequest(info, collectionSettings, currentBook); try { if(Program.RunningUnitTests) { endpointRegistration.Handler(request); } else { var formForSynchronizing = Application.OpenForms.Cast<Form>().Last(); if (endpointRegistration.HandleOnUIThread && formForSynchronizing.InvokeRequired) { formForSynchronizing.Invoke(endpointRegistration.Handler, request); } else { endpointRegistration.Handler(request); } } if(!info.HaveOutput) { throw new ApplicationException(string.Format("The EndpointHandler for {0} never called a Succeeded(), Failed(), or ReplyWith() Function.", info.RawUrl.ToString())); } } catch (Exception e) { SIL.Reporting.ErrorReport.ReportNonFatalExceptionWithMessage(e, info.RawUrl); return false; } return true; }
public static string GetResponseString(IRequestInfo requestInfo) { using (var dataStream = GetResponseStream(requestInfo)) using (var reader = new StreamReader(dataStream, Encoding)) { return reader.ReadToEnd(); } }
public void Reset(IRequestInfo requestInfo) { _requestInfo = requestInfo; _carriageReturn = false; _statusBuffer.Length = 0; _bufferPosition = 0; _bufferDataLength = 0; _responseDataPosition = 0; _currentResponse = new Response(new[] { "ERROR", "INCOMPLETE" }); }
public static Stream GetResponseStream(IRequestInfo requestInfo) { if (requestInfo == null) throw new ArgumentNullException("requestInfo"); var webRequest = (HttpWebRequest)WebRequest.Create(requestInfo.UriString); webRequest.UserAgent = UserAgent; webRequest.Accept = Accept; if (requestInfo.PostContent != null) webRequest.Method = WebRequestMethods.Http.Post; else webRequest.Method = WebRequestMethods.Http.Get; if (requestInfo.PostContent != null) { byte[] byteArray = requestInfo.PostContent; // Set the ContentType property of the WebRequest. webRequest.ContentType = requestInfo.ContentType; webRequest.ContentLength = byteArray.Length; // Get the request stream. using (Stream dataStream = webRequest.GetRequestStream()) { // Write the data to the request stream. dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); } } Stream memoryStream = new MemoryStream(); try { using (WebResponse response = webRequest.GetResponse()) using (Stream dataStream = response.GetResponseStream()) { if (dataStream != null) { CopyStream(dataStream, memoryStream); dataStream.Close(); } response.Close(); } } catch (WebException ex) { //TODO: Добавить протоколирование Debug.WriteLine(ex.Message); } return memoryStream; }
public static Stream GetResponseStream(IRequestInfo requestInfo) { if (requestInfo == null) throw new ArgumentNullException("requestInfo"); var webRequest = WebRequest.Create(requestInfo.UriString) as HttpWebRequest; webRequest.UserAgent = USERAGENT; webRequest.Accept = ACCEPT; if (requestInfo.PostContent != null) webRequest.Method = WebRequestMethods.Http.Post; else webRequest.Method = WebRequestMethods.Http.Get; if (requestInfo.PostContent != null) { byte[] byteArray = requestInfo.PostContent; webRequest.ContentType = requestInfo.ContentType; webRequest.ContentLength = byteArray.Length; using (Stream dataStream = webRequest.GetRequestStream()) { dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); } } Stream memoryStream = new MemoryStream(); try { using (WebResponse response = webRequest.GetResponse()) using (Stream dataStream = response.GetResponseStream()) { if (dataStream != null) { CopyStream(dataStream, memoryStream); dataStream.Close(); } response.Close(); } } catch (WebException ex) { Debug.WriteLine(ex.Message); } return memoryStream; }
/// <inheritdoc /> public async Task Process(IRequestInfo request) { if (request == null) { throw new ArgumentNullException("request"); } var httpRequest = request as RequestInfo; if (httpRequest == null) { throw new ArgumentOutOfRangeException("request"); } await AuthenticateInternal(httpRequest); }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) return true; if (!_useCache) return false; var imageFile = GetLocalPathWithoutQuery(info); // only process images var isSvg = imageFile.EndsWith(".svg", StringComparison.OrdinalIgnoreCase); if (!IsImageTypeThatCanBeDegraded(imageFile) && !isSvg) return false; imageFile = imageFile.Replace("thumbnail", ""); var processImage = !isSvg; // This happens with the new way we are serving css files if (!RobustFile.Exists(imageFile)) { var fileName = Path.GetFileName(imageFile); var sourceDir = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot); imageFile = Directory.EnumerateFiles(sourceDir, fileName, SearchOption.AllDirectories).FirstOrDefault(); // image file not found if (string.IsNullOrEmpty(imageFile)) return false; // BL-2368: Do not process files from the BloomBrowserUI directory. These files are already in the state we // want them. Running them through _cache.GetPathToResizedImage() is not necessary, and in PNG files // it converts all white areas to transparent. This is resulting in icons which only contain white // (because they are rendered on a dark background) becoming completely invisible. processImage = false; } if (processImage) { // thumbnail requests have the thumbnail parameter set in the query string var thumb = info.GetQueryParameters()["thumbnail"] != null; imageFile = _cache.GetPathToResizedImage(imageFile, thumb); if (string.IsNullOrEmpty(imageFile)) return false; } info.ReplyWithImage(imageFile); return true; }
/// <inheritdoc /> public Task<object> Transform(IRequestMapping requestMapping, IRequestInfo request, object result, object[] arguments) { RequestInfo requestInfo; MethodInfo underlyingMethod; if (!CanOutputHypermedia((underlyingMethod = requestMapping.Operation.UnderlyingMethod).ReturnType, requestInfo = request as RequestInfo)) { return Task.FromResult(result); } int totalItems = ((IEnumerable)result).Cast<object>().Count(); int skip = 0; int take = 0; bool canOutputHypermedia = false; KeyValuePair<Verb, MethodInfo> method; if ((requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController<>), typeof(IAsyncController<>)) != null) && (!Equals(method = requestMapping.Target.GetType().DiscoverCrudMethods().FirstOrDefault(entry => entry.Value == underlyingMethod), default(KeyValuePair<Verb, MethodInfo>)))) { switch (method.Key.ToString()) { case "": var parameters = underlyingMethod.GetParameters(); var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList(); totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1); if ((arguments[1] != null) && (arguments[2] != null)) { skip = (int)arguments[1]; take = ((take = (int)arguments[2]) == 0 ? 0 : Math.Min(take, totalItems)); canOutputHypermedia = (requestMapping.ArgumentSources[1] == ArgumentValueSources.Bound) && (requestMapping.ArgumentSources[2] == ArgumentValueSources.Bound); } break; } } if (!canOutputHypermedia) { return Task.FromResult(result); } var namedGraphSelector = _namedGraphSelectorFactory.NamedGraphSelector; ILocallyControlledNamedGraphSelector locallyControlledNamedGraphSelector = namedGraphSelector as ILocallyControlledNamedGraphSelector; result = (locallyControlledNamedGraphSelector == null ? TransformCollection(result, requestInfo.Url, totalItems, skip, take) : TransformColectionWithLock(locallyControlledNamedGraphSelector, result, requestInfo, totalItems, skip, take)); return Task.FromResult(result); }
public new string SubstitutePathParameters(string path, IRequestInfo requestInfo) { return(base.SubstitutePathParameters(path, requestInfo)); }
/// <summary> /// Initialises a new instance of the <see cref="RequestBodySerializerInfo"/> structure /// </summary> /// <param name="requestInfo">Information about the request</param> /// <param name="formatProvider">Format provider to use</param> public RequestBodySerializerInfo(IRequestInfo requestInfo, IFormatProvider formatProvider) { this.RequestInfo = requestInfo; this.FormatProvider = formatProvider; }
public override string ToString(IRequestInfo request) { return("do nothing"); }
public CommonService(IUnitOfWork unitOfWork, IRequestInfo requestInfo) : base(unitOfWork) { this.requestInfo = requestInfo; }
/// <summary> /// 通讯干扰时调用此函数 /// </summary> /// <param name="info"></param> public abstract void CommunicateError(IRequestInfo info);
/// <summary> /// Given a set of headers, apply them to the given HttpRequestMessage. Headers will override any of that type already present /// </summary> /// <param name="requestInfo">RequestInfo for this request</param> /// <param name="requestMessage">HttpRequestMessage to add the headers to</param> /// <param name="headers">Headers to add</param> /// <param name="areMethodHeaders">True if these headers came from the method, false if they came from the class</param> protected virtual void ApplyHeadersSet( IRequestInfo requestInfo, HttpRequestMessage requestMessage, IEnumerable <KeyValuePair <string, string?> > headers, bool areMethodHeaders) { HttpContent?dummyContent = null; var headersGroups = headers.GroupBy(x => x.Key); foreach (var headersGroup in headersGroups) { // Can't use .Contains, as it will throw if the header isn't a valid type if (requestMessage.Headers.Any(x => x.Key == headersGroup.Key)) { requestMessage.Headers.Remove(headersGroup.Key); } // Null values are used to remove instances of a header, but should not be added string[] headersToAdd = headersGroup.Select(x => x.Value).Where(x => x != null).ToArray() !; if (!headersToAdd.Any()) { continue; } bool added = requestMessage.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd); // If we failed, it's probably a content header. Try again there if (!added) { // If it's a method header, then add a dummy body if necessary // If it's a class header, then add a dummy body if there isn't one but there is a [Body] // parameter, otherwise ignore it. // If it's a class header, then throw only if it isn't a content header (but don't add a dummy body containing it) if (requestMessage.Content != null) { if (requestMessage.Content.Headers.Any(x => x.Key == headersGroup.Key)) { requestMessage.Content.Headers.Remove(headersGroup.Key); } added = requestMessage.Content.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd); } else { // If they've added a content header, my reading of the RFC is that we are actually sending a body (even if they haven't // said what should be in it), and therefore we need to send Content-Length if (dummyContent == null) { dummyContent = new ByteArrayContent(ArrayUtil.Empty <byte>()); } added = dummyContent.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd); if (added && (areMethodHeaders || requestInfo.BodyParameterInfo != null)) { requestMessage.Content = dummyContent; } } } // Technically this can be triggered, but I can't come up with any inputs which will if (!added) { throw new ArgumentException($"Header {headersGroup.Key} could not be added. Maybe it's associated with HTTP responses, or it's malformed?"); } } }
/// <summary> /// Given an IRequestInfo and pre-substituted relative path, constructs a URI with the right query parameters /// </summary> /// <param name="baseAddress">Base address to start with, with placeholders already substituted</param> /// <param name="basePath">Base path to start with, with placeholders already substituted</param> /// <param name="path">Path to start with, with placeholders already substituted</param> /// <param name="requestInfo">IRequestInfo to retrieve the query parameters from</param> /// <returns>Constructed URI; relative if 'path' was relative, otherwise absolute</returns> protected virtual Uri ConstructUri(string baseAddress, string basePath, string path, IRequestInfo requestInfo) { UriBuilder uriBuilder; try { // For the base address, we choose HttpClient.BaseAddress, unless it's null where we choose baseAdress // If path is absolute, then baseAddress and basePath are both ignored. // If path starts with /, then basePath is ignored but baseAddress is not. // If basePath is absolute, then baseAddress is ignored. string trimmedPath = (path ?? string.Empty).TrimStart('/'); // Here, a leading slash will strip the path from baseAddress var uri = new Uri(trimmedPath, UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri && path?.StartsWith("/") != true && !string.IsNullOrEmpty(basePath)) { uri = Prepend(uri, basePath.TrimStart('/')); } if (!uri.IsAbsoluteUri) { string?resolvedBaseAddress = this.httpClient.BaseAddress?.ToString() ?? baseAddress?.TrimStart('/'); if (!string.IsNullOrEmpty(resolvedBaseAddress)) { uri = Prepend(uri, resolvedBaseAddress !); } } // If it's still relative, 'new UriBuilder(Uri)' won't accept it, but 'new UriBuilder(string)' will // (by prepending 'http://'). uriBuilder = uri.IsAbsoluteUri ? new UriBuilder(uri) : new UriBuilder(uri.ToString()); Uri Prepend(Uri uri, string path) { // Need to make sure it ends with a trailing slash, or appending our relative path will strip // the last path component (assuming there is one) if (!path.EndsWith("/") && !string.IsNullOrEmpty(uri.OriginalString)) { path += '/'; } return(new Uri(path + uri.OriginalString, UriKind.RelativeOrAbsolute)); } } catch (FormatException e) { // The original exception doesn't actually include the path - which is not helpful to the user throw new FormatException(string.Format("Path '{0}' is not valid: {1}", path, e.Message)); } string?query = this.BuildQueryParam(uriBuilder.Query, requestInfo.RawQueryParameters, requestInfo.QueryParams, requestInfo.QueryProperties, requestInfo); // Mono's UriBuilder.Query setter will always add a '?', so we can end up with a double '??'. uriBuilder.Query = query.TrimStart('?'); return(uriBuilder.Uri); }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) { return(true); } var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if (r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png") && r.Contains("thumbnail")) { info.ContentType = "image/png"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { info.ContentType = GetContentType(Path.GetExtension(r)); string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r); //request.QueryString.GetValues() info.ReplyWithFileContent(path); } return(true); }
public new void ApplyHeaders(IRequestInfo requestInfo, HttpRequestMessage requestMessage) { base.ApplyHeaders(requestInfo, requestMessage); }
public async Task <Boolean> SignInUserAsync(String loginProvider, String providerKey, String token, IRequestInfo request) { AppUser user = await UserManager.FindAsync(new UserLoginInfo(loginProvider, providerKey)); if (user == null) { return(false); } // TODO: generate token //Boolean result = await UserManager.VerifyUserTokenAsync(user.Id, loginProvider, token); //if (result) //{ await SignInManager.SignInAsync(user, false, false); if (request != null) { user.LastLoginDate = DateTime.Now; user.LastLoginHost = request.HostText; await _userManager.UpdateAsync(user); } return(true); //} //return result; }
protected override Task<HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo) { this.RequestInfo = requestInfo; return this.ResponseMessage; }
public override string ToString(IRequestInfo request) { return(ToString()); }
// Every path should return false or send a response. // Otherwise we can get a timeout error as the browser waits for a response. // // NOTE: this method gets called on different threads! protected override bool ProcessRequest(IRequestInfo info) { var localPath = GetLocalPathWithoutQuery(info); //enhance: something feeds back these branding logos with a weird URL, that shouldn't be. if(localPath.IndexOf("api/branding") > 20) // this 20 is just arbitrary... the point is, if it doesn't start with api/branding, it is bogus { return false; } if (localPath.ToLower().StartsWith("api/")) { var endpoint = localPath.Substring(3).ToLowerInvariant().Trim(new char[] {'/'}); foreach (var pair in _endpointRegistrations.Where(pair => Regex.Match(endpoint, "^" + //must match the beginning pair.Key.ToLower() ).Success)) { lock(SyncObj) { return ApiRequest.Handle(pair.Value, info, CurrentCollectionSettings, _bookSelection.CurrentSelection); } } } //OK, no more obvious simple API requests, dive into the rat's nest of other possibilities if (base.ProcessRequest(info)) return true; if(localPath.Contains("CURRENTPAGE")) //useful when debugging. E.g. http://localhost:8091/bloom/CURRENTPAGE.htm will always show the page we're on. { localPath = _keyToCurrentPage; } string content; bool gotSimulatedPage; lock (_urlToSimulatedPageContent) { gotSimulatedPage = _urlToSimulatedPageContent.TryGetValue(localPath, out content); } if (gotSimulatedPage) { info.ContentType = "text/html"; info.WriteCompleteOutput(content ?? ""); return true; } if (localPath.StartsWith(OriginalImageMarker) && IsImageTypeThatCanBeDegraded(localPath)) { // Path relative to simulated page file, and we want the file contents without modification. // (Note that the simulated page file's own URL starts with this, so it's important to check // for that BEFORE we do this check.) localPath = localPath.Substring(OriginalImageMarker.Length + 1); return ProcessAnyFileContent(info, localPath); } if (localPath.StartsWith("error", StringComparison.InvariantCulture)) { ProcessError(info); return true; } else if (localPath.StartsWith("i18n/", StringComparison.InvariantCulture)) { if (ProcessI18N(localPath, info)) return true; } else if (localPath.StartsWith("directoryWatcher/", StringComparison.InvariantCulture)) return ProcessDirectoryWatcher(info); else if (localPath.StartsWith("localhost/", StringComparison.InvariantCulture)) { var temp = LocalHostPathToFilePath(localPath); if (RobustFile.Exists(temp)) localPath = temp; } // this is used only by the readium viewer else if (localPath.StartsWith("node_modules/jquery/dist/jquery.js")) { localPath = BloomFileLocator.GetBrowserFile("jquery.min.js"); // Avoid having "output/browser/" removed on Linux developer machines. // GetBrowserFile adds output to the path on developer machines, but not user installs. return ProcessContent(info, localPath); } //Firefox debugger, looking for a source map, was prefixing in this unexpected //way. localPath = localPath.Replace("output/browser/", ""); return ProcessContent(info, localPath); }
/// <summary> /// Serializes the value of a path parameter, using an appropriate method /// </summary> /// <param name="pathParameter">Path parameter to serialize</param> /// <param name="requestInfo">RequestInfo representing the request</param> /// <returns>Serialized value</returns> protected virtual KeyValuePair <string, string?> SerializePathParameter(PathParameterInfo pathParameter, IRequestInfo requestInfo) { switch (pathParameter.SerializationMethod) { case PathSerializationMethod.ToString: return(pathParameter.SerializeToString(this.FormatProvider)); case PathSerializationMethod.Serialized: if (this.RequestPathParamSerializer == null) { throw new InvalidOperationException("Cannot serialize path parameter when RequestPathParamSerializer is null. Please set RequestPathParamSerializer"); } var result = pathParameter.SerializeValue(this.RequestPathParamSerializer, requestInfo, this.FormatProvider); return(result); default: throw new InvalidOperationException("Should never get here"); } }
private static bool GetTopicList(IRequestInfo info) { var keyToLocalizedTopicDictionary = new Dictionary<string, string>(); foreach (var topic in BookInfo.TopicsKeys) { var localized = LocalizationManager.GetDynamicString("Bloom", "Topics." + topic, topic, @"shows in the topics chooser in the edit tab"); keyToLocalizedTopicDictionary.Add(topic, localized); } string localizedNoTopic = LocalizationManager.GetDynamicString("Bloom", "Topics.NoTopic", "No Topic", @"shows in the topics chooser in the edit tab"); var arrayOfKeyValuePairs = from key in keyToLocalizedTopicDictionary.Keys orderby keyToLocalizedTopicDictionary[key] select string.Format("\"{0}\": \"{1}\"",key,keyToLocalizedTopicDictionary[key]); var pairs = arrayOfKeyValuePairs.Concat(","); info.ContentType = "application/json"; var data = string.Format("{{\"NoTopic\": \"{0}\", {1} }}", localizedNoTopic, pairs); info.WriteCompleteOutput(data); /* var data = new {NoTopic = localizedNoTopic, pairs = arrayOfKeyValuePairs}; * var serializeObject = JsonConvert.SerializeObject(data, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, }); */ //info.WriteCompleteOutput(serializeObject); return true; }
/// <summary> /// Called from interface methods which return a Task{HttpResponseMessage} /// </summary> /// <param name="requestInfo">IRequestInfo to construct the request from</param> /// <returns>Task containing the result of the request</returns> public virtual async Task <HttpResponseMessage> RequestWithResponseMessageAsync(IRequestInfo requestInfo) { // It's the user's responsibility to dispose this var response = await this.SendRequestAsync(requestInfo, readBody : false).ConfigureAwait(false); return(response); }
private static void ProcessError(IRequestInfo info) { // pop-up the error messages if a debugger is attached or an environment variable is set var popUpErrors = Debugger.IsAttached || !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DEBUG_BLOOM")); var post = info.GetPostDataWhenFormEncoded(); // log the error message var errorMsg = post["message"] + Environment.NewLine + "File: " + post["url"].FromLocalhost() + Environment.NewLine + "Line: " + post["line"] + " Column: " + post["column"] + Environment.NewLine; Logger.WriteMinorEvent(errorMsg); Console.Out.WriteLine(errorMsg); if (popUpErrors) Shell.DisplayProblemToUser(errorMsg); }
private void GetStoreBooks(IRequestInfo info) { //enhance: it will eventually work better to do sorting client-side, according to user's current prefs var reply = new StringBuilder(); var list = new List<BookCollection>(); list.AddRange(_sourceCollectionsesList.GetSourceCollections()); list.Sort(CompareBookCollections); foreach (BookCollection collection in list) { reply.AppendFormat("<li class='collectionGroup'><h2>{0}</h2><ul class='collection'>", collection.Name); reply.Append(GetBookListItems(collection.GetBookInfos())); reply.AppendFormat(@"</ul></li>"); } info.WriteCompleteOutput(reply.ToString()); }
private static void ReplyWithFileContentAndType(IRequestInfo info, string path) { info.ContentType = GetContentType(Path.GetExtension(path)); info.ReplyWithFileContent(path); }
public Repository(IRequestInfo <TDbContext> requestInfo) => this.RequestInfo = requestInfo;
private bool CheckForSampleTextChanges(IRequestInfo info) { lock (SyncObj) { if (_sampleTextsWatcher == null) { var path = Path.Combine(Path.GetDirectoryName(CurrentCollectionSettings.SettingsFilePath), "Sample Texts"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); _sampleTextsWatcher = new FileSystemWatcher { Path = path }; _sampleTextsWatcher.Created += SampleTextsOnChange; _sampleTextsWatcher.Changed += SampleTextsOnChange; _sampleTextsWatcher.Renamed += SampleTextsOnChange; _sampleTextsWatcher.Deleted += SampleTextsOnChange; _sampleTextsWatcher.EnableRaisingEvents = true; } } lock (_sampleTextsWatcher) { var hasChanged = _sampleTextsChanged; // Reset the changed flag. // NOTE: we are only resetting the flag if it was "true" when we checked in case the FileSystemWatcher detects a change // after we check the flag but we reset it to false before we check again. if (hasChanged) _sampleTextsChanged = false; info.ContentType = "text/plain"; info.WriteCompleteOutput(hasChanged ? "yes" : "no"); return true; } }
private Task Callback(IServiceBusMessage message, IRequestInfo requestInfo) => Task.CompletedTask;
private bool ProcessAnyFileContent(IRequestInfo info, string localPath) { string modPath = localPath; string path = null; // When JavaScript inserts our path into the html it replaces the three magic html characters with these substitutes. // We need to convert back in order to match our key. Then, reverse the change we made to deal with quotation marks. string tempPath = UnescapeUrlQuotes(modPath.Replace("<", "<").Replace(">", ">").Replace("&", "&")); if (RobustFile.Exists(tempPath)) modPath = tempPath; try { if (localPath.Contains("favicon.ico")) //need something to pacify Chrome path = FileLocator.GetFileDistributedWithApplication("BloomPack.ico"); // Is this request the full path to an image file? For most images, we just have the filename. However, in at // least one use case, the image we want isn't in the folder of the PDF we're looking at. That case is when // we are looking at a "folio", a book that gathers up other books into one big PDF. In that case, we want // to find the image in the correct book folder. See AddChildBookContentsToFolio(); var possibleFullImagePath = localPath; // "OriginalImages/" at the beginning means we're generating a pdf and want full images, // but it has nothing to do with the actual file location. if (localPath.StartsWith("OriginalImages/")) possibleFullImagePath = localPath.Substring(15); if(RobustFile.Exists(possibleFullImagePath) && Path.IsPathRooted(possibleFullImagePath)) { path = possibleFullImagePath; } else { // Surprisingly, this method will return localPath unmodified if it is a fully rooted path // (like C:\... or \\localhost\C$\...) to a file that exists. So this execution path // can return contents of any file that exists if the URL gives its full path...even ones that // are generated temp files most certainly NOT distributed with the application. path = FileLocator.GetFileDistributedWithApplication(BloomFileLocator.BrowserRoot, modPath); } } catch (ApplicationException) { // ignore. Assume this means that this class/method cannot serve that request, but something else may. } //There's probably a eventual way to make this problem go away, // but at the moment FF, looking for source maps to go with css, is // looking for those maps where we said the css was, which is in the actual // book folders. So instead redirect to our browser file folder. if (string.IsNullOrEmpty(path) || !RobustFile.Exists(path)) { var startOfBookLayout = localPath.IndexOf("bookLayout"); if (startOfBookLayout > 0) path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookLayout)); var startOfBookEdit = localPath.IndexOf("bookEdit"); if (startOfBookEdit > 0) path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookEdit)); } if (!RobustFile.Exists(path) && localPath.StartsWith("pageChooser/") && IsImageTypeThatCanBeReturned(localPath)) { // if we're in the page chooser dialog and looking for a thumbnail representing an image in a // template page, look for that thumbnail in the book that is the template source, // rather than in the folder that stores the page choose dialog HTML and code. var templatePath = Path.Combine(_bookSelection.CurrentSelection.FindTemplateBook().FolderPath, localPath.Substring("pageChooser/".Length)); if (RobustFile.Exists(templatePath)) { info.ReplyWithImage(templatePath); return true; } } // Use '%25' to detect that the % in a Url encoded character (for example space encoded as %20) was encoded as %25. // In this example we would have %2520 in info.RawUrl and %20 in localPath instead of a space. Note that if an // image has a % in the filename, like 'The other 50%', and it isn't doubly encoded, then this shouldn't be a // problem because we're triggering here only if the file isn't found. if (!RobustFile.Exists(localPath) && info.RawUrl.Contains("%25")) { // possibly doubly encoded? decode one more time and try. See https://silbloom.myjetbrains.com/youtrack/issue/BL-3835. // Some existing books have somehow acquired Url encoded coverImage data like the following: // <div data-book="coverImage" lang="*"> // The%20Moon%20and%20The%20Cap_Cover.png // </div> // This leads to data being stored doubly encoded in the program's run-time data. The coverImage data is supposed to be // Html/Xml encoded (using &), not Url encoded (using %). path = System.Web.HttpUtility.UrlDecode(localPath); } if (!RobustFile.Exists(path) && IsImageTypeThatCanBeReturned(localPath)) { // last resort...maybe we are in the process of renaming a book (BL-3345) and something mysteriously is still using // the old path. For example, I can't figure out what hangs on to the old path when an image is changed after // altering the main book title. var currentFolderPath = Path.Combine(_bookSelection.CurrentSelection.FolderPath, Path.GetFileName(localPath)); if (RobustFile.Exists(currentFolderPath)) { info.ReplyWithImage(currentFolderPath); return true; } } if (!RobustFile.Exists(path)) { // On developer machines, we can lose part of path earlier. Try one more thing. path = info.LocalPathWithoutQuery.Substring(7); // skip leading "/bloom/"); } if (!File.Exists(path)) { ReportMissingFile(localPath,path); return false; } info.ContentType = GetContentType(Path.GetExtension(modPath)); info.ReplyWithFileContent(path); return true; }
/// <summary> /// Serialize the (typed) value using the given serializer /// </summary> /// <param name="serializer">Serializer to use</param> /// <param name="requestInfo">RequestInfo representing the request</param> /// <param name="formatProvider"><see cref="IFormatProvider"/> to use if the value implements <see cref="IFormattable"/></param> /// <returns>Serialized value</returns> public abstract HttpContent SerializeValue(RequestBodySerializer serializer, IRequestInfo requestInfo, IFormatProvider formatProvider);
private bool ProcessContent(IRequestInfo info, string localPath) { if (localPath.EndsWith(".css")) { return ProcessCssFile(info, localPath); } switch (localPath) { case "currentPageContent": info.ContentType = "text/html"; info.WriteCompleteOutput(CurrentPageContent ?? ""); return true; case "toolboxContent": info.ContentType = "text/html"; info.WriteCompleteOutput(ToolboxContent ?? ""); return true; case "availableFontNames": info.ContentType = "application/json"; var list = new List<string>(Browser.NamesOfFontsThatBrowserCanRender()); list.Sort(); info.WriteCompleteOutput(JsonConvert.SerializeObject(new{fonts = list})); return true; case "authorMode": info.ContentType = "text/plain"; info.WriteCompleteOutput(AuthorMode ? "true" : "false"); return true; case "topics": return GetTopicList(info); } return ProcessAnyFileContent(info, localPath); }
public new Uri ConstructUri(string basePath, string relativePath, IRequestInfo requestInfo) { return(base.ConstructUri(basePath, relativePath, requestInfo)); }
private bool ProcessCssFile(IRequestInfo info, string localPath) { // BL-2219: "OriginalImages" means we're generating a pdf and want full images, // but it has nothing to do with css files and defeats the following 'if' localPath = localPath.Replace("OriginalImages/", ""); // is this request the full path to a real file? if (RobustFile.Exists(localPath) && Path.IsPathRooted(localPath)) { // Typically this will be files in the book or collection directory, since the browser // is supplying the path. // currently this only applies to settingsCollectionStyles.css, and customCollectionStyles.css var cssFile = Path.GetFileName(localPath); if ((cssFile == "settingsCollectionStyles.css") || (cssFile == "customCollectionStyles.css")) { info.ContentType = "text/css"; info.ReplyWithFileContent(localPath); return true; } } // if not a full path, try to find the correct file var fileName = Path.GetFileName(localPath); // try to find the css file in the xmatter and templates if (_fileLocator == null) { _fileLocator = Program.OptimizedFileLocator; } var path = _fileLocator.LocateFile(fileName); // if still not found, and localPath is an actual file path, use it if (string.IsNullOrEmpty(path) && RobustFile.Exists(localPath)) path = localPath; if (string.IsNullOrEmpty(path)) { // it's just possible we need to add BloomBrowserUI to the path (in the case of the AddPage dialog) var lastTry = FileLocator.GetFileDistributedWithApplication(true, BloomFileLocator.BrowserRoot, localPath); if(RobustFile.Exists(lastTry)) path = lastTry; } // return false if the file was not found if (string.IsNullOrEmpty(path)) return false; info.ContentType = "text/css"; info.ReplyWithFileContent(path); return true; }
public new HttpContent ConstructContent(IRequestInfo requestInfo) { return(base.ConstructContent(requestInfo)); }
private bool ProcessDirectoryWatcher(IRequestInfo info) { // thread synchronization is done in CheckForSampleTextChanges. var dirName = info.GetPostDataWhenFormEncoded()["dir"]; if (dirName == "Sample Texts") { if (CheckForSampleTextChanges(info)) return true; } return false; }
public new Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo, bool readBody) { return(base.SendRequestAsync(requestInfo, readBody)); }
private bool ProcessI18N(string localPath, IRequestInfo info) { lock (I18NLock) { return I18NHandler.HandleRequest(localPath, info, CurrentCollectionSettings); } }
private void GetLibraryBooks(IRequestInfo info) { var books = _booksInProjectLibrary.GetBookInfos(); info.WriteCompleteOutput(GetBookListItems(books)); }
public UnitOfWork(IRequestInfo requestInfo) { this._requestInfo = requestInfo; }
public AuditableRepository(IRequestInfo <TDbContext> requestInfo) : base(requestInfo) { }
public new Uri ConstructUri(string relativePath, IRequestInfo requestInfo) { return base.ConstructUri(relativePath, requestInfo); }
/// <summary> /// Initialises a new instance of the <see cref="RequestQueryParamSerializerInfo"/> structure /// </summary> /// <param name="requestInfo">Information about the request</param> /// <param name="format">Format string specified using <see cref="QueryAttribute.Format"/></param> public RequestQueryParamSerializerInfo(IRequestInfo requestInfo, string format) { this.RequestInfo = requestInfo; this.Format = format; }
public new string SubstitutePathParameters(IRequestInfo requestInfo) { return base.SubstitutePathParameters(requestInfo); }
/// <summary> /// Build up a query string from the initial query string, raw query parameter, and any query params (which need to be combined) /// </summary> /// <param name="initialQueryString">Initial query string, present from the URI the user specified in the Get/etc parameter</param> /// <param name="rawQueryParameters">The raw query parameters, if any</param> /// <param name="queryParams">The query parameters which need serializing (or an empty collection)</param> /// <param name="queryProperties">The query parameters from properties which need serialializing (or an empty collection)</param> /// <param name="requestInfo">RequestInfo representing the request</param> /// <returns>Query params combined into a query string</returns> protected virtual string BuildQueryParam( string initialQueryString, IEnumerable <RawQueryParameterInfo> rawQueryParameters, IEnumerable <QueryParameterInfo> queryParams, IEnumerable <QueryParameterInfo> queryProperties, IRequestInfo requestInfo) { var serializedQueryParams = queryParams.SelectMany(x => this.SerializeQueryParameter(x, requestInfo)); var serializedQueryProperties = queryProperties.SelectMany(x => this.SerializeQueryParameter(x, requestInfo)); var serializedRawQueryParameters = rawQueryParameters.Select(x => x.SerializeToString(this.FormatProvider)); if (this.QueryStringBuilder != null) { var info = new QueryStringBuilderInfo(initialQueryString, serializedRawQueryParameters, serializedQueryParams, serializedQueryProperties, requestInfo, this.FormatProvider); return(this.QueryStringBuilder.Build(info)); } // Implementation copied from FormUrlEncodedContent var sb = new StringBuilder(); void AppendQueryString(string query) { if (sb.Length > 0) { sb.Append('&'); } sb.Append(query); } string Encode(string?data) { if (string.IsNullOrEmpty(data)) { return(string.Empty); } return(Uri.EscapeDataString(data).Replace("%20", "+")); } if (!string.IsNullOrEmpty(initialQueryString)) { AppendQueryString(initialQueryString.Replace("%20", "+")); } foreach (string?serializedRawQueryParameter in serializedRawQueryParameters) { AppendQueryString(serializedRawQueryParameter); } foreach (var kvp in serializedQueryParams.Concat(serializedQueryProperties)) { if (kvp.Key == null) { AppendQueryString(Encode(kvp.Value)); } else { AppendQueryString(Encode(this.ToStringHelper(kvp.Key))); sb.Append('='); sb.Append(Encode(kvp.Value)); } } return(sb.ToString()); }
public new HttpContent ConstructContent(IRequestInfo requestInfo) { return base.ConstructContent(requestInfo); }
/// <summary> /// Serializes the value of a query parameter, using an appropriate method /// </summary> /// <param name="queryParameter">Query parameter to serialize</param> /// <param name="requestInfo">RequestInfo representing the request</param> /// <returns>Serialized value</returns> protected virtual IEnumerable <KeyValuePair <string, string?> > SerializeQueryParameter(QueryParameterInfo queryParameter, IRequestInfo requestInfo) { switch (queryParameter.SerializationMethod) { case QuerySerializationMethod.ToString: return(queryParameter.SerializeToString(this.FormatProvider)); case QuerySerializationMethod.Serialized: if (this.RequestQueryParamSerializer == null) { throw new InvalidOperationException("Cannot serialize query parameter when RequestQueryParamSerializer is null. Please set RequestQueryParamSerializer"); } var result = queryParameter.SerializeValue(this.RequestQueryParamSerializer, requestInfo, this.FormatProvider); return(result ?? Enumerable.Empty <KeyValuePair <string, string?> >()); default: throw new InvalidOperationException("Should never get here"); } }
/// <summary> /// Calls this.ResponseDeserializer.ReadAndDeserializeAsync, after checking it's not null /// </summary> /// <typeparam name="T">Type of object to deserialize into</typeparam> /// <param name="content">String content read from the response</param> /// <param name="response">Response to deserialize from</param> /// <param name="requestInfo">RequestInfo representing the request</param> /// <returns>A task containing the deserialized response</returns> protected virtual T Deserialize <T>(string?content, HttpResponseMessage response, IRequestInfo requestInfo) { if (this.ResponseDeserializer == null) { throw new InvalidOperationException("Cannot deserialize a response when ResponseDeserializer is null. Please set ResponseDeserializer"); } return(this.ResponseDeserializer.Deserialize <T>(content, response, new ResponseDeserializerInfo(requestInfo))); }
public new Task<HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo) { return base.SendRequestAsync(requestInfo); }
/// <summary> /// 通讯中断时调用此函数 /// </summary> /// <param name="info"></param> public abstract void CommunicateInterrupt(IRequestInfo info);
public Task DispatchCommand <TCommand>(TCommand message, IRequestInfo requestInfo) where TCommand : ICommand { _serviceBusMessagePublisher.PublishCommand(message, requestInfo); _logger.LogInformation($"{message.GetType().Name} dispatched for user: " + requestInfo.UserId); return(Task.CompletedTask); }
// Every path should return false or send a response. // Otherwise we can get a timeout error as the browser waits for a response. // // NOTE: this method gets called on different threads! public bool ProcessRequest(IRequestInfo info, string localPath) { var localPathLc = localPath.ToLowerInvariant(); if (localPathLc.StartsWith("api/", StringComparison.InvariantCulture)) { var endpointPath = localPath.Substring(3).ToLowerInvariant().Trim(new char[] { '/' }); foreach (var pair in _endpointRegistrations.Where(pair => Regex.Match(endpointPath, "^" + //must match the beginning pair.Key.ToLower() ).Success)) { var endpointRegistration = pair.Value; if (endpointRegistration.RequiresSync) { // A single synchronization object won't do, because when processing a request to create a thumbnail or update a preview, // we have to load the HTML page the thumbnail is based on, or other HTML pages (like one used to figure what's // visible in a preview). If the page content somehow includes // an api request (api/branding/image is one example), that request will deadlock if the // api/pageTemplateThumbnail request already has the main lock. // Another case is the Bloom Reader preview, where the whole UI is rebuilt at the same time as the preview. // This leads to multiple api requests racing with the preview one, and it was possible for all // the server threads to be processing these and waiting for SyncObject while the updatePreview // request held the lock...and the request for the page that would free the lock was sitting in // the queue, waiting for a thread. // To the best of my knowledge, there's no shared data between the thumbnailing and preview processes and any // other api requests, so it seems safe to have one lock that prevents working on multiple // thumbnails/previews at the same time, and one that prevents working on other api requests at the same time. var syncOn = SyncObj; if (localPathLc.StartsWith("api/pagetemplatethumbnail", StringComparison.InvariantCulture) || localPathLc == "api/publish/android/thumbnail" || localPathLc == "api/publish/android/updatepreview") { syncOn = ThumbnailsAndPreviewsSyncObj; } else if (localPathLc.StartsWith("api/i18n/")) { syncOn = I18NLock; } // Basically what lock(syncObj) {} is syntactic sugar for (see its documentation), // but we wrap RegisterThreadBlocking/Unblocked around acquiring the lock. // We need the more complicated structure because we would like RegisterThreadUnblocked // to be called immediately after acquiring the lock (notably, before Handle() is called), // but we also want to handle the case where Monitor.Enter throws an exception. bool lockAcquired = false; try { // Try to acquire lock BloomServer._theOneInstance.RegisterThreadBlocking(); try { // Blocks until it either succeeds (lockAcquired will then always be true) or throws (lockAcquired will stay false) Monitor.Enter(syncOn, ref lockAcquired); } finally { BloomServer._theOneInstance.RegisterThreadUnblocked(); } // Lock has been acquired. ApiRequest.Handle(endpointRegistration, info, CurrentCollectionSettings, _bookSelection.CurrentSelection); // Even if ApiRequest.Handle() fails, return true to indicate that the request was processed and there // is no further need for the caller to continue trying to process the request as a filename. // See https://issues.bloomlibrary.org/youtrack/issue/BL-6763. return(true); } finally { if (lockAcquired) { Monitor.Exit(syncOn); } } } else { // Up to api's that request no sync to do things right! ApiRequest.Handle(endpointRegistration, info, CurrentCollectionSettings, _bookSelection.CurrentSelection); // Even if ApiRequest.Handle() fails, return true to indicate that the request was processed and there // is no further need for the caller to continue trying to process the request as a filename. // See https://issues.bloomlibrary.org/youtrack/issue/BL-6763. return(true); } } } return(false); }
/// <summary> /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object /// </summary> /// <param name="info"></param> public void MakeReply(IRequestInfo info) { var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if(r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png")) { info.ContentType = "image/png"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r); //request.QueryString.GetValues() info.WriteCompleteOutput(File.ReadAllText(path)); } }
protected override Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo, bool readBody) { this.RequestInfo = requestInfo; return(this.ResponseMessage); }