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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
 public static string GetPhysicalPath(this IRequest httpReq) => HostContext.ResolvePhysicalPath(httpReq.PathInfo, httpReq);
Example #5
0
        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));
 }
Example #8
0
        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);
        }
Example #9
0
 public static string GetCompressionType(this IRequest request) =>
 HostContext.AssertAppHost().GetCompressionType(request);
Example #10
0
 public static IAuthSession AssertAuthenticatedSession(this IRequest req, bool reload = false)
 => HostContext.AppHost.HasValidAuthSecret(req)
         ? HostContext.GetAuthSecretSession()
         : HostContext.AppHost.AssertAuthenticated(req.GetSession(), req);
Example #11
0
 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);
Example #12
0
 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);
        }
Example #14
0
        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;
        }
Example #16
0
 public static IVirtualFile GetVirtualFile(this IRequest httpReq) => HostContext.ResolveVirtualFile(httpReq.PathInfo, httpReq);
Example #17
0
 public static void EndNotModified(this IResponse res, string description = null)
 {
     res.StatusCode        = 304;
     res.StatusDescription = description ?? HostContext.ResolveLocalizedString(LocalizedStrings.NotModified);
     res.EndRequest();
 }
Example #18
0
        /// <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));
 }
Example #20
0
 /// <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));
 }
Example #22
0
        public virtual T ResolveService <T>()
        {
            var service = TryResolve <T>();

            return(HostContext.ResolveService(Request, service));
        }
Example #23
0
        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);
            }
        }
Example #24
0
 public EventSubscription(IResponse response)
 {
     this.response   = response;
     this.Meta       = new Dictionary <string, string>();
     this.WriteEvent = HostContext.GetPlugin <ServerEventsFeature>().WriteEvent;
 }
Example #25
0
            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));
            }
Example #26
0
        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);
        }
Example #27
0
 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;
        }