public static async Task <bool> HandleValidCache(this IRequest req, CacheInfo cacheInfo, CancellationToken token = default) { if (cacheInfo == null) { return(false); } ICacheClient cache; ICacheClientAsync cacheAsync = null; // only non-null if native ICacheClientAsync exists if (cacheInfo.LocalCache) { cache = HostContext.AppHost.GetMemoryCacheClient(req); } else { HostContext.AppHost.TryGetNativeCacheClient(req, out cache, out cacheAsync); } var cacheControl = HostContext.GetPlugin <HttpCacheFeature>().BuildCacheControlHeader(cacheInfo); var res = req.Response; DateTime?lastModified = null; var doHttpCaching = cacheInfo.MaxAge != null || cacheInfo.CacheControl != CacheControl.None; if (doHttpCaching) { lastModified = cacheAsync != null ? await cacheAsync.GetAsync <DateTime?>(cacheInfo.LastModifiedKey(), token).ConfigAwait() : cache.Get <DateTime?>(cacheInfo.LastModifiedKey()); if (req.HasValidCache(lastModified)) { if (cacheControl != null) { res.AddHeader(HttpHeaders.CacheControl, cacheControl); } res.EndNotModified(); return(true); } } var encoding = !cacheInfo.NoCompression ? req.GetCompressionType() : null; var useCacheKey = encoding != null ? cacheInfo.CacheKey + "." + encoding : cacheInfo.CacheKey; var responseBytes = cacheAsync != null ? await cacheAsync.GetAsync <byte[]>(useCacheKey, token).ConfigAwait() : cache.Get <byte[]>(useCacheKey); if (responseBytes != null) { if (encoding != null) { res.AddHeader(HttpHeaders.ContentEncoding, encoding); } if (cacheInfo.VaryByUser) { res.AddHeader(HttpHeaders.Vary, "Cookie"); } if (cacheControl != null) { res.AddHeader(HttpHeaders.CacheControl, cacheControl); } if (!doHttpCaching) { lastModified = cache.Get <DateTime?>(cacheInfo.LastModifiedKey()); } if (lastModified != null) { res.AddHeader(HttpHeaders.LastModified, lastModified.Value.ToUniversalTime().ToString("r")); } await res.WriteBytesToResponse(responseBytes, req.ResponseContentType, token).ConfigAwait(); return(true); } return(false); }
public List <PostmanRequest> GetRequests(Postman request, string parentId, IEnumerable <Operation> operations) { var ret = new List <PostmanRequest>(); var feature = HostContext.GetPlugin <PostmanFeature>(); var headers = feature.Headers ?? ("Accept: " + MimeTypes.Json); if (Response is IHttpResponse httpRes) { if (request.ssopt != null || request.sspid != null || request.ssid != null) { if (feature.EnableSessionExport != true) { throw new ArgumentException("PostmanFeature.EnableSessionExport is not enabled"); } } if (request.ssopt != null) { Request.AddSessionOptions(request.ssopt); } if (request.sspid != null) { httpRes.Cookies.AddPermanentCookie(SessionFeature.PermanentSessionId, request.sspid); } if (request.ssid != null) { httpRes.Cookies.AddSessionCookie(SessionFeature.SessionId, request.ssid, (HostContext.Config.UseSecureCookies && Request.IsSecureConnection)); } } foreach (var op in operations) { if (!HostContext.Metadata.IsVisible(base.Request, op)) { continue; } var allVerbs = op.Actions.Concat( op.Routes.SelectMany(x => x.Verbs)) .SelectMany(x => x == ActionContext.AnyAction ? feature.DefaultVerbsForAny : new List <string> { x }) .ToHashSet(); var propertyTypes = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); op.RequestType.GetSerializableFields() .Each(x => propertyTypes[x.Name] = x.FieldType.AsFriendlyName(feature)); op.RequestType.GetSerializableProperties() .Each(x => propertyTypes[x.Name] = x.PropertyType.AsFriendlyName(feature)); foreach (var route in op.Routes) { var routeVerbs = route.Verbs.Contains(ActionContext.AnyAction) ? feature.DefaultVerbsForAny.ToArray() : route.Verbs; var restRoute = route.ToRestRoute(); foreach (var verb in routeVerbs) { allVerbs.Remove(verb); //exclude handled verbs var routeData = restRoute.QueryStringVariables .Map(x => new PostmanData { key = x, value = "", type = "text", }) .ApplyPropertyTypes(propertyTypes); ret.Add(new PostmanRequest { collectionId = parentId, id = SessionExtensions.CreateRandomSessionId(), method = verb, url = Request.GetBaseUrl().CombineWith(restRoute.Path.ToPostmanPathVariables()), name = GetName(feature, request, op.RequestType, restRoute.Path), description = op.RequestType.GetDescription(), pathVariables = !HttpUtils.HasRequestBody(verb) ? restRoute.Variables.Concat(routeData.Select(x => x.key)) .ApplyPropertyTypes(propertyTypes) : null, data = HttpUtils.HasRequestBody(verb) ? routeData : null, dataMode = "params", headers = headers, version = 2, time = DateTime.UtcNow.ToUnixTimeMs(), }); } } var emptyRequest = op.RequestType.CreateInstance(); var virtualPath = emptyRequest.ToReplyUrlOnly(); var requestParams = propertyTypes .Map(x => new PostmanData { key = x.Key, value = x.Value, type = "text", }); ret.AddRange(allVerbs.Select(verb => new PostmanRequest { collectionId = parentId, id = SessionExtensions.CreateRandomSessionId(), method = verb, url = Request.GetBaseUrl().CombineWith(virtualPath), pathVariables = !HttpUtils.HasRequestBody(verb) ? requestParams.Select(x => x.key) .ApplyPropertyTypes(propertyTypes) : null, name = GetName(feature, request, op.RequestType, virtualPath), description = op.RequestType.GetDescription(), data = HttpUtils.HasRequestBody(verb) ? requestParams : null, dataMode = "params", headers = headers, version = 2, time = DateTime.UtcNow.ToUnixTimeMs(), })); } return(ret); }
public async Task <object> AnyAsync(AutoQueryMetadata request) { if (NativeTypesMetadata == null) { throw new NotSupportedException("AutoQueryViewer requires NativeTypesFeature"); } var feature = HostContext.GetPlugin <AutoQueryMetadataFeature>(); var config = feature.AutoQueryViewerConfig; if (config == null) { throw new NotSupportedException("AutoQueryViewerConfig is missing"); } if (config.ServiceBaseUrl == null) { config.ServiceBaseUrl = base.Request.GetBaseUrl(); } if (config.ServiceName == null) { config.ServiceName = HostContext.ServiceName; } var userSession = await Request.GetSessionAsync(); var typesConfig = NativeTypesMetadata.GetConfig(new TypesMetadata { BaseUrl = Request.GetBaseUrl() }); foreach (var type in feature.ExportTypes) { typesConfig.ExportTypes.Add(type); } var metadataTypes = NativeTypesMetadata.GetMetadataTypes(Request, typesConfig, op => HostContext.Metadata.IsAuthorized(op, Request, userSession)); var response = new AutoQueryMetadataResponse { Config = config, UserInfo = new AutoQueryViewerUserInfo { IsAuthenticated = userSession.IsAuthenticated, }, Operations = new List <AutoQueryOperation>(), Types = new List <MetadataType>(), }; var includeTypeNames = new HashSet <string>(); foreach (var op in metadataTypes.Operations) { if (op.Request.Inherits != null && (op.Request.Inherits.Name.StartsWith("QueryDb`") || op.Request.Inherits.Name.StartsWith("QueryData`")) ) { if (config.OnlyShowAnnotatedServices) { var serviceAttrs = op.Request.Attributes.Safe(); var attr = serviceAttrs.FirstOrDefault(x => x.Name + "Attribute" == nameof(AutoQueryViewerAttribute)); if (attr == null) { continue; } } var inheritArgs = op.Request.Inherits.GenericArgs.Safe().ToArray(); response.Operations.Add(new AutoQueryOperation { Request = op.Request.Name, Routes = op.Routes, From = inheritArgs.First(), To = inheritArgs.Last(), }); response.Types.Add(op.Request); op.Request.GetReferencedTypeNames(metadataTypes).Each(x => includeTypeNames.Add(x)); } } var allTypes = metadataTypes.GetAllTypes().ToList(); var types = allTypes.Where(x => includeTypeNames.Contains(x.Name)).ToList(); //Add referenced types to type name search types.SelectMany(x => x.GetReferencedTypeNames(metadataTypes)).Each(x => includeTypeNames.Add(x)); //Only need to seek 1-level deep in AutoQuery's (db.LoadSelect) types = allTypes.Where(x => includeTypeNames.Contains(x.Name)).ToList(); response.Types.AddRange(types); response.UserInfo.QueryCount = response.Operations.Count; feature.MetadataFilter?.Invoke(response); return(response); }
public static string GetPhysicalPath(this IRequest httpReq) => HostContext.ResolvePhysicalPath(httpReq.PathInfo, httpReq);
public object Any(AutoQueryMetadata request) { if (NativeTypesMetadata == null) { throw new NotSupportedException("AutoQueryViewer requries NativeTypesFeature"); } var feature = HostContext.GetPlugin <AutoQueryFeature>(); var config = feature.AutoQueryViewerConfig; if (config == null) { throw new NotSupportedException("AutoQueryViewerConfig is missing"); } if (config.ServiceBaseUrl == null) { config.ServiceBaseUrl = base.Request.ResolveBaseUrl(); } if (config.ServiceName == null) { config.ServiceName = HostContext.ServiceName; } var typesConfig = NativeTypesMetadata.GetConfig(new TypesMetadata { BaseUrl = Request.GetBaseUrl() }); var metadataTypes = NativeTypesMetadata.GetMetadataTypes(Request, typesConfig); var response = new AutoQueryMetadataResponse { Config = feature.AutoQueryViewerConfig, Operations = new List <AutoQueryOperation>(), Types = new List <MetadataType>(), }; var includeTypeNames = new HashSet <string>(); foreach (var op in metadataTypes.Operations) { if (op.Request.Inherits != null && op.Request.Inherits.Name.StartsWith("QueryBase`")) { if (config.OnlyShowAnnotatedServices) { var serviceAttrs = op.Request.Attributes.Safe(); var attr = serviceAttrs.FirstOrDefault(x => x.Name + "Attribute" == typeof(AutoQueryViewerAttribute).Name); if (attr == null) { continue; } } var inheritArgs = op.Request.Inherits.GenericArgs.Safe().ToArray(); response.Operations.Add(new AutoQueryOperation { Request = op.Request.Name, From = inheritArgs.First(), To = inheritArgs.Last(), }); response.Types.Add(op.Request); op.Request.GetReferencedTypeNames().Each(x => includeTypeNames.Add(x)); } } var types = metadataTypes.Types.Where(x => includeTypeNames.Contains(x.Name)); //Add referenced types to type name search types.SelectMany(x => x.GetReferencedTypeNames()).Each(x => includeTypeNames.Add(x)); //Only need to seek 1-level deep in AutoQuery's (db.LoadSelect) types = metadataTypes.Types.Where(x => includeTypeNames.Contains(x.Name)); response.Types.AddRange(types); return(response); }
public static IVirtualDirectory GetVirtualDirectory(this IRequest httpReq) { return(HostContext.ResolveVirtualDirectory(httpReq.PathInfo, httpReq)); }
public static string ResolveAbsoluteUrl(this IRequest httpReq, string url) { return(HostContext.ResolveAbsoluteUrl(url, httpReq)); }
internal static async Task <IAuthSession> GetSessionInternalAsync(this IRequest httpReq, bool reload, bool async, CancellationToken token = default) { if (httpReq == null) { return(null); } if (HostContext.TestMode) { var mockSession = httpReq.TryResolve <IAuthSession>(); //testing if (mockSession != null) { return(mockSession); } } httpReq.Items.TryGetValue(Keywords.Session, out var oSession); if (reload && (oSession as IAuthSession)?.FromToken != true) // can't reload FromToken sessions from cache { oSession = null; } var appHost = HostContext.AppHost; if (oSession == null && !httpReq.Items.ContainsKey(Keywords.HasPreAuthenticated)) { try { await appHost.ApplyPreAuthenticateFiltersAsync(httpReq, httpReq.Response).ConfigAwait(); httpReq.Items.TryGetValue(Keywords.Session, out oSession); } catch (Exception ex) { Log.Error("Error in GetSession() when ApplyPreAuthenticateFilters", ex); /*treat errors as non-existing session*/ } } var sessionId = httpReq.GetSessionId(); var session = oSession as IAuthSession; if (session != null) { session = appHost.OnSessionFilter(httpReq, session, sessionId); } if (session != null) { return(session); } if (appHost.HasValidAuthSecret(httpReq)) { session = HostContext.GetAuthSecretSession(); if (session != null) { return(session); } } var sessionKey = SessionFeature.GetSessionKey(sessionId); if (sessionKey != null) { session = async ? await httpReq.GetCacheClientAsync().GetAsync <IAuthSession>(sessionKey, token).ConfigAwait() : httpReq.GetCacheClient().Get <IAuthSession>(sessionKey); if (session != null) { session = appHost.OnSessionFilter(httpReq, session, sessionId); } } if (session == null) { var newSession = SessionFeature.CreateNewSession(httpReq, sessionId); session = appHost.OnSessionFilter(httpReq, newSession, sessionId) ?? newSession; } httpReq.Items[Keywords.Session] = session; return(session); }
public static string GetCompressionType(this IRequest request) => HostContext.AssertAppHost().GetCompressionType(request);
public static IAuthSession AssertAuthenticatedSession(this IRequest req, bool reload = false) => HostContext.AppHost.HasValidAuthSecret(req) ? HostContext.GetAuthSecretSession() : HostContext.AppHost.AssertAuthenticated(req.GetSession(), req);
public static async Task <IAuthSession> AssertAuthenticatedSessionAsync(this IRequest req, bool reload = false, CancellationToken token = default) => HostContext.AppHost.HasValidAuthSecret(req) ? HostContext.GetAuthSecretSession() : HostContext.AppHost.AssertAuthenticated(await req.GetSessionAsync(token: token).ConfigAwait(), req);
public MetadataTypesGenerator GetGenerator() => (HostContext.TryResolve <INativeTypesMetadata>() ?? new NativeTypesMetadata(HostContext.AppHost.Metadata, MetadataTypesConfig)) .GetGenerator();
public static bool HandleValidCache(this IRequest req, CacheInfo cacheInfo) { if (cacheInfo == null) { return(false); } var res = req.Response; var cache = cacheInfo.LocalCache ? HostContext.LocalCache : HostContext.Cache; DateTime?lastModified = null; var doHttpCaching = cacheInfo.MaxAge != null || cacheInfo.CacheControl != CacheControl.None; if (doHttpCaching) { lastModified = cache.Get <DateTime?>(cacheInfo.LastModifiedKey()); if (req.HasValidCache(lastModified)) { res.EndNotModified(); return(true); } } var encoding = req.GetCompressionType(); var responseBytes = encoding != null ? cache.Get <byte[]>(cacheInfo.CacheKey + "." + encoding) : cache.Get <byte[]>(cacheInfo.CacheKey); if (responseBytes != null) { if (encoding != null) { res.AddHeader(HttpHeaders.ContentEncoding, encoding); } if (cacheInfo.VaryByUser) { res.AddHeader(HttpHeaders.Vary, "Cookie"); } var cacheControl = HostContext.GetPlugin <HttpCacheFeature>().BuildCacheControlHeader(cacheInfo); if (cacheControl != null) { res.AddHeader(HttpHeaders.CacheControl, cacheControl); } if (!doHttpCaching) { lastModified = cache.Get <DateTime?>(cacheInfo.LastModifiedKey()); } if (lastModified != null) { res.AddHeader(HttpHeaders.LastModified, lastModified.Value.ToUniversalTime().ToString("r")); } res.WriteBytesToResponse(responseBytes, req.ResponseContentType); return(true); } return(false); }
public static string GetProfileUrl(this IAuthSession authSession, string defaultUrl = null) { var profile = HostContext.TryResolve <IAuthMetadataProvider>(); return(profile == null ? defaultUrl : profile.GetProfileUrl(authSession, defaultUrl)); }
public override async Task ExecuteAsync(IRequest req, IResponse res, object requestDto) { if (req.Verb != HttpMethods.Get && req.Verb != HttpMethods.Head) { return; } if (req.IsInProcessRequest()) { return; } var feature = HostContext.GetPlugin <HttpCacheFeature>(); if (feature == null) { throw new NotSupportedException(ErrorMessages.CacheFeatureMustBeEnabled.LocalizeFmt(req, "[CacheResponse]")); } if (feature.DisableCaching) { return; } var keyBase = "res:" + req.RawUrl; var keySuffix = MimeTypes.GetExtension(req.ResponseContentType); var modifiers = ""; if (req.ResponseContentType == MimeTypes.Json) { string jsonp = req.GetJsonpCallback(); if (jsonp != null) { modifiers = "jsonp:" + jsonp.SafeVarName(); } } if (VaryByUser) { modifiers += (modifiers.Length > 0 ? "+" : "") + "user:"******"+" : "") + "role:" + role; } } } } } if (VaryByHeaders != null && VaryByHeaders.Length > 0) { foreach (var header in VaryByHeaders) { var value = req.GetHeader(header); if (!string.IsNullOrEmpty(value)) { modifiers += (modifiers.Length > 0 ? "+" : "") + $"{header}:{value}"; } } } if (modifiers.Length > 0) { keySuffix += "+" + modifiers; } var cacheInfo = new CacheInfo { KeyBase = keyBase, KeyModifiers = keySuffix, ExpiresIn = Duration > 0 ? TimeSpan.FromSeconds(Duration) : (TimeSpan?)null, MaxAge = MaxAge >= 0 ? TimeSpan.FromSeconds(MaxAge) : (TimeSpan?)null, CacheControl = CacheControl, VaryByUser = VaryByUser, LocalCache = LocalCache, NoCompression = NoCompression, }; if (await req.HandleValidCache(cacheInfo).ConfigAwait()) { return; } req.Items[Keywords.CacheInfo] = cacheInfo; }
public static IVirtualFile GetVirtualFile(this IRequest httpReq) => HostContext.ResolveVirtualFile(httpReq.PathInfo, httpReq);
public static void EndNotModified(this IResponse res, string description = null) { res.StatusCode = 304; res.StatusDescription = description ?? HostContext.ResolveLocalizedString(LocalizedStrings.NotModified); res.EndRequest(); }
/// <summary> /// Writes to response. /// Response headers are customizable by implementing IHasOptions an returning Dictionary of Http headers. /// </summary> /// <param name="response">The response.</param> /// <param name="result">Whether or not it was implicity handled by ServiceStack's built-in handlers.</param> /// <param name="defaultAction">The default action.</param> /// <param name="request">The serialization context.</param> /// <param name="bodyPrefix">Add prefix to response body if any</param> /// <param name="bodySuffix">Add suffix to response body if any</param> /// <returns></returns> public static Task <bool> WriteToResponse(this IResponse response, object result, ResponseSerializerDelegate defaultAction, IRequest request, byte[] bodyPrefix, byte[] bodySuffix) { using (Profiler.Current.Step("Writing to Response")) { var defaultContentType = request.ResponseContentType; try { if (result == null) { response.EndRequestWithNoContent(); return(TrueTask); } ApplyGlobalResponseHeaders(response); var httpResult = result as IHttpResult; if (httpResult != null) { if (httpResult.RequestContext == null) { httpResult.RequestContext = request; } var paddingLength = bodyPrefix != null ? bodyPrefix.Length : 0; if (bodySuffix != null) { paddingLength += bodySuffix.Length; } httpResult.PaddingLength = paddingLength; var httpError = httpResult as IHttpError; if (httpError != null) { response.Dto = httpError.CreateErrorResponse(); if (response.HandleCustomErrorHandler(request, defaultContentType, httpError.Status, response.Dto)) { return(TrueTask); } } response.Dto = response.Dto ?? httpResult.GetDto(); response.StatusCode = httpResult.Status; response.StatusDescription = httpResult.StatusDescription ?? httpResult.StatusCode.ToString(); if (string.IsNullOrEmpty(httpResult.ContentType)) { httpResult.ContentType = defaultContentType; } response.ContentType = httpResult.ContentType; } else { response.Dto = result; } /* Mono Error: Exception: Method not found: 'System.Web.HttpResponse.get_Headers' */ var responseOptions = result as IHasOptions; if (responseOptions != null) { //Reserving options with keys in the format 'xx.xxx' (No Http headers contain a '.' so its a safe restriction) const string reservedOptions = "."; foreach (var responseHeaders in responseOptions.Options) { if (responseHeaders.Key.Contains(reservedOptions)) { continue; } if (responseHeaders.Key == HttpHeaders.ContentLength) { response.SetContentLength(long.Parse(responseHeaders.Value)); continue; } Log.DebugFormat("Setting Custom HTTP Header: {0}: {1}", responseHeaders.Key, responseHeaders.Value); response.AddHeader(responseHeaders.Key, responseHeaders.Value); } } //ContentType='text/html' is the default for a HttpResponse //Do not override if another has been set if (response.ContentType == null || response.ContentType == MimeTypes.Html) { response.ContentType = defaultContentType; } if (bodyPrefix != null && response.ContentType.IndexOf(MimeTypes.Json, StringComparison.InvariantCultureIgnoreCase) >= 0) { response.ContentType = MimeTypes.JavaScript; } if (HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(response.ContentType)) { response.ContentType += ContentFormat.Utf8Suffix; } var disposableResult = result as IDisposable; if (WriteToOutputStream(response, result, bodyPrefix, bodySuffix)) { response.Flush(); //required for Compression if (disposableResult != null) { disposableResult.Dispose(); } return(TrueTask); } if (httpResult != null) { result = httpResult.Response; } var responseText = result as string; if (responseText != null) { if (bodyPrefix != null) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } WriteTextToResponse(response, responseText, defaultContentType); if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } return(TrueTask); } if (defaultAction == null) { throw new ArgumentNullException("defaultAction", String.Format( "As result '{0}' is not a supported responseType, a defaultAction must be supplied", (result != null ? result.GetType().GetOperationName() : ""))); } if (bodyPrefix != null) { response.OutputStream.Write(bodyPrefix, 0, bodyPrefix.Length); } if (result != null) { defaultAction(request, result, response); } if (bodySuffix != null) { response.OutputStream.Write(bodySuffix, 0, bodySuffix.Length); } if (disposableResult != null) { disposableResult.Dispose(); } return(FalseTask); } catch (Exception originalEx) { HostContext.RaiseUncaughtException(request, response, request.OperationName, originalEx); if (!HostContext.Config.WriteErrorsToResponse) { return(originalEx.AsTaskException <bool>()); } var errorMessage = String.Format( "Error occured while Processing Request: [{0}] {1}", originalEx.GetType().GetOperationName(), originalEx.Message); try { if (!response.IsClosed) { response.WriteErrorToResponse( request, defaultContentType, request.OperationName, errorMessage, originalEx, (int)HttpStatusCode.InternalServerError); } } catch (Exception writeErrorEx) { //Exception in writing to response should not hide the original exception Log.Info("Failed to write error to response: {0}", writeErrorEx); return(originalEx.AsTaskException <bool>()); } return(TrueTask); } finally { response.EndRequest(skipHeaders: true); } } }
public static IVirtualNode GetVirtualNode(this IRequest httpReq) { return(HostContext.ResolveVirtualNode(httpReq.PathInfo, httpReq)); }
/// <summary> /// End a ServiceStack Request /// </summary> public static void EndRequest(this IResponse httpRes, bool skipHeaders = false) { httpRes.EndHttpHandlerRequest(skipHeaders: skipHeaders); HostContext.CompleteRequest(httpRes.Request); }
public static string ResolveBaseUrl(this IRequest httpReq) { return(HostContext.ResolveAbsoluteUrl("~/", httpReq)); }
public virtual T ResolveService <T>() { var service = TryResolve <T>(); return(HostContext.ResolveService(Request, service)); }
public static object Cache(this ICacheClient cacheClient, string cacheKey, object responseDto, IRequest request, TimeSpan?expireCacheIn = null) { request.Response.Dto = responseDto; cacheClient.Set(cacheKey, responseDto, expireCacheIn); if (!request.ResponseContentType.IsBinary()) { string serializedDto = SerializeToString(request, responseDto); string modifiers = null; if (request.ResponseContentType.MatchesContentType(MimeTypes.Json)) { var jsonp = request.GetJsonpCallback(); if (jsonp != null) { modifiers = ".jsonp," + jsonp.SafeVarName(); serializedDto = jsonp + "(" + serializedDto + ")"; //Add a default expire timespan for jsonp requests, //because they aren't cleared when calling ClearCaches() if (expireCacheIn == null) { expireCacheIn = HostContext.Config.DefaultJsonpCacheExpiration; } } } var cacheKeySerialized = GetCacheKeyForSerialized(cacheKey, request.ResponseContentType, modifiers); cacheClient.Set(cacheKeySerialized, serializedDto, expireCacheIn); var compressionType = request.GetCompressionType(); bool doCompression = compressionType != null; if (doCompression) { var lastModified = HostContext.GetPlugin <HttpCacheFeature>().ShouldAddLastModifiedToOptimizedResults() && String.IsNullOrEmpty(request.Response.GetHeader(HttpHeaders.CacheControl)) ? DateTime.UtcNow : (DateTime?)null; var cacheKeySerializedZip = GetCacheKeyForCompressed(cacheKeySerialized, compressionType); byte[] compressedSerializedDto = serializedDto.Compress(compressionType); cacheClient.Set(cacheKeySerializedZip, compressedSerializedDto, expireCacheIn); if (lastModified != null) { cacheClient.Set(DateCacheKey(cacheKeySerializedZip), lastModified.Value.Ticks, expireCacheIn); } return(compressedSerializedDto != null ? new CompressedResult(compressedSerializedDto, compressionType, request.ResponseContentType) { Status = request.Response.StatusCode, LastModified = lastModified, } : null); } return(serializedDto); } else { string modifiers = null; byte[] serializedDto = HostContext.ContentTypes.SerializeToBytes(request, responseDto); var cacheKeySerialized = GetCacheKeyForSerialized(cacheKey, request.ResponseContentType, modifiers); cacheClient.Set(cacheKeySerialized, serializedDto, expireCacheIn); return(serializedDto); } }
public EventSubscription(IResponse response) { this.response = response; this.Meta = new Dictionary <string, string>(); this.WriteEvent = HostContext.GetPlugin <ServerEventsFeature>().WriteEvent; }
public override async Task ProcessRequestAsync(IRequest httpReq, IResponse httpRes, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(httpReq, httpRes)) { return; } httpRes.ContentType = MimeTypes.Xml; var xml = StringBuilderCache.Allocate(); xml.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xml.Append("<urlset"); foreach (var ns in feature.UrlSetNamespaces) { xml.Append(" {0}=\"{1}\"".Fmt(ns.Key, ns.Value)); } xml.AppendLine(">"); if (feature.CustomXml?.UrlSetHeaderXml != null) { xml.AppendLine(feature.CustomXml.UrlSetHeaderXml); } foreach (var url in urlSet.Safe()) { xml.AppendLine("<url>"); if (url.Location != null) { xml.AppendLine($" <loc>{url.Location.EncodeXml()}</loc>"); } if (url.LastModified != null) { xml.AppendLine($" <lastmod>{url.LastModified.Value:yyyy-MM-dd}</lastmod>"); } if (url.ChangeFrequency != null) { xml.AppendLine($" <changefreq>{url.ChangeFrequency.Value.ToString().ToLower()}</changefreq>"); } if (url.Priority != null) { xml.AppendLine($" <priority>{url.Priority.Value.ToString(CultureInfo.InvariantCulture)}</priority>"); } if (url.CustomXml != null) { xml.AppendLine(url.CustomXml); } xml.AppendLine("</url>"); } if (feature.CustomXml?.UrlSetFooterXml != null) { xml.AppendLine(feature.CustomXml.UrlSetFooterXml); } xml.AppendLine("</urlset>"); var text = StringBuilderCache.Retrieve(xml); await httpRes.EndHttpHandlerRequestAsync(skipClose : true, afterHeaders : r => r.WriteAsync(text)); }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(req, res)) { return(EmptyTask); } var feature = HostContext.GetPlugin <ServerEventsFeature>(); var session = req.GetSession(); if (feature.LimitToAuthenticatedUsers && !session.IsAuthenticated) { session.ReturnFailedAuthentication(req); return(EmptyTask); } res.ContentType = MimeTypes.ServerSentEvents; res.AddHeader(HttpHeaders.CacheControl, "no-cache"); res.ApplyGlobalResponseHeaders(); res.UseBufferedStream = false; res.KeepAlive = true; if (feature.OnInit != null) { feature.OnInit(req); } res.Flush(); var serverEvents = req.TryResolve <IServerEvents>(); var userAuthId = session != null ? session.UserAuthId : null; var anonUserId = serverEvents.GetNextSequence("anonUser"); var userId = userAuthId ?? ("-" + anonUserId); var displayName = session.GetSafeDisplayName() ?? "user" + anonUserId; var now = DateTime.UtcNow; var subscriptionId = SessionExtensions.CreateRandomSessionId(); //Handle both ?channel=A,B,C or ?channels=A,B,C var channels = new List <string>(); var channel = req.QueryString["channel"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } channel = req.QueryString["channels"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } if (channels.Count == 0) { channels = EventSubscription.UnknownChannel.ToList(); } var subscription = new EventSubscription(res) { CreatedAt = now, LastPulseAt = now, Channels = channels.ToArray(), SubscriptionId = subscriptionId, UserId = userId, UserName = session != null ? session.UserName : null, DisplayName = displayName, SessionId = req.GetPermanentSessionId(), IsAuthenticated = session != null && session.IsAuthenticated, OnPublish = feature.OnPublish, Meta = { { "userId", userId }, { "displayName", displayName }, { "channels", string.Join(",", channels) }, { AuthMetadataProvider.ProfileUrlKey, session.GetProfileUrl() ?? AuthMetadataProvider.DefaultNoProfileImgUrl }, } }; if (feature.OnCreated != null) { feature.OnCreated(subscription, req); } var heartbeatUrl = req.ResolveAbsoluteUrl("~/".CombineWith(feature.HeartbeatPath)) .AddQueryParam("id", subscriptionId); var unRegisterUrl = req.ResolveAbsoluteUrl("~/".CombineWith(feature.UnRegisterPath)) .AddQueryParam("id", subscriptionId); var privateArgs = new Dictionary <string, string>(subscription.Meta) { { "id", subscriptionId }, { "unRegisterUrl", unRegisterUrl }, { "heartbeatUrl", heartbeatUrl }, { "heartbeatIntervalMs", ((long)feature.HeartbeatInterval.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) }, { "idleTimeoutMs", ((long)feature.IdleTimeout.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) } }; if (feature.OnConnect != null) { feature.OnConnect(subscription, privateArgs); } serverEvents.Register(subscription, privateArgs); var tcs = new TaskCompletionSource <bool>(); subscription.OnDispose = _ => { try { res.EndHttpHandlerRequest(skipHeaders: true); } catch { } tcs.SetResult(true); }; return(tcs.Task); }
public T GetPlugin <T>() where T : class, IPlugin => GetResolver()?.TryResolve <T>() ?? HostContext.GetPlugin <T>();
public override void Execute(IRequest req, IResponse res, object requestDto) { if (req.Verb != HttpMethods.Get && req.Verb != HttpMethods.Head) { return; } var feature = HostContext.GetPlugin <HttpCacheFeature>(); if (feature == null) { throw new NotSupportedException(ErrorMessages.CacheFeatureMustBeEnabled.Fmt("[CacheResponse]")); } var keyBase = "res:" + req.RawUrl; var keySuffix = MimeTypes.GetExtension(req.ResponseContentType); var modifiers = ""; if (req.ResponseContentType == MimeTypes.Json) { string jsonp = req.GetJsonpCallback(); if (jsonp != null) { modifiers = "jsonp:" + jsonp.SafeVarName(); } } if (VaryByUser) { modifiers += (modifiers.Length > 0 ? "+" : "") + "user:"******"+" : "") + "role:" + role; } } } } if (modifiers.Length > 0) { keySuffix += "+" + modifiers; } var cacheInfo = new CacheInfo { KeyBase = keyBase, KeyModifiers = keySuffix, ExpiresIn = Duration > 0 ? TimeSpan.FromSeconds(Duration) : (TimeSpan?)null, MaxAge = MaxAge >= 0 ? TimeSpan.FromSeconds(MaxAge) : (TimeSpan?)null, CacheControl = CacheControl, VaryByUser = VaryByUser, LocalCache = LocalCache, }; if (req.HasValidCache(cacheInfo)) { return; } req.Items[Keywords.CacheInfo] = cacheInfo; }