Exemplo n.º 1
0
        /// <summary>
        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler" /> interface.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        public void ProcessHttpApiContextContainer(HttpApiContextContainer <TRequest, TResponse> context)
        {
            context.EntryStamp = DateTime.UtcNow;
            context.SetResponseHeader(HttpConstants.HttpHeader.SERVERENTRYTIME, context.EntryStamp.ToFullDateTimeTzString());

            var acceptEncoding = context.TryGetRequestHeader(HttpConstants.HttpHeader.AcceptEncoding);

            try
            {
                //First of all, clean thread info for context.
                ContextHelper.Reinitialize();

                context.TraceId       = context.TryGetRequestHeader(HttpConstants.HttpHeader.TRACEID);
                context.TraceSequence = context.TryGetRequestHeader(HttpConstants.HttpHeader.TRACESEQUENCE).ToNullableInt32();

                Prepare(context.Request);

                if (context.HttpMethod.Equals(HttpConstants.HttpMethod.Options, StringComparison.OrdinalIgnoreCase))
                {
                    if (AllowOptions)
                    {
                        //Return directly. IIS would append following headers by default, according to what exactly web.config have.
                        //Access-Control-Allow-Origin: *
                        //Access-Control-Allow-Headers: Content-Type
                        //Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

                        context.SetResponseHeader(HttpConstants.HttpHeader.SERVEREXITTIME, DateTime.UtcNow.ToFullDateTimeTzString());

                        return;
                    }
                }

                // Authentication has already done inside ProcessRoute.
                var runtimeContext = ProcessRoute(context);
                runtimeContext.CheckNullObject(nameof(runtimeContext));
                context.RuntimeContext = runtimeContext;

                // Fill basic context info.

                var userAgentHeaderKey = context.Settings?.OriginalUserAgentHeaderKey;

                //ContextHelper.ConsistContext(
                //    // TOKEN
                //    context.TryGetRequestHeader((context.Settings?.TokenHeaderKey).SafeToString(HttpConstants.HttpHeader.TOKEN)),
                //    // Settings
                //    context.Settings,
                //    // IP Address
                //    context.TryGetRequestHeader((context.Settings?.OriginalIpAddressHeaderKey).SafeToString(HttpConstants.HttpHeader.ORIGINAL)).SafeToString(context.ClientIpAddress),
                //    // User Agent
                //    string.IsNullOrWhiteSpace(userAgentHeaderKey) ? context.UserAgent : context.TryGetRequestHeader(userAgentHeaderKey).SafeToString(context.UserAgent),
                //    // Culture Code
                //    context.QueryString.Get(HttpConstants.QueryString.Language).SafeToString(context.UserLanguages.SafeFirstOrDefault()).EnsureCultureCode(),
                //     // Current Uri
                //     context.Url,
                //     HttpExtension.GetBasicAuthentication(context.TryGetRequestHeader(HttpConstants.HttpHeader.Authorization).DecodeBase64()),
                //     runtimeContext.ApiRouterIdentifier
                //    );

                if (runtimeContext.OperationParameters?.EntitySynchronizationMode != null)
                {
                    ContextHelper.ApiContext.LastSynchronizedStamp = context.TryGetRequestHeader(runtimeContext.OperationParameters.EntitySynchronizationMode.IfModifiedSinceKey).ObjectToDateTime();
                }

                // Fill finished.
                if (string.IsNullOrWhiteSpace(runtimeContext.Realm) && runtimeContext.Version.Equals(ApiConstants.BuiltInFeatureVersionKeyword, StringComparison.OrdinalIgnoreCase))
                {
                    string contentType;
                    var    buildInResult = ProcessBuiltInFeature(context, runtimeContext, context.IsLocal, out contentType);
                    PackageResponse(context, buildInResult, new RuntimeApiOperationParameters {
                        ContentType = contentType
                    }, null, acceptEncoding, runtimeContext.IsVoid ?? false, context.Settings);
                }
                else
                {
                    //Initialize additional header keys
                    if ((runtimeContext.OperationParameters?.CustomizedHeaderKeys).HasItem())
                    {
                        var currentApiContext = ContextHelper.ApiContext;

                        foreach (var one in runtimeContext.OperationParameters.CustomizedHeaderKeys)
                        {
                            currentApiContext.CustomizedHeaders.Merge(one, context.TryGetRequestHeader(one));
                        }
                    }

                    InitializeContext(context.Request, runtimeContext);

                    byte[] body = context.ReadRequestBody();
                    context.CollectTrackingInfo(body.LongLength);

                    if (runtimeContext.Exception != null)
                    {
                        throw runtimeContext.Exception;
                    }

                    ApiTraceContext.Enter(runtimeContext, setNameAsMajor: true);
                    string jsonBody = null;

                    try
                    {
                        if (runtimeContext.ApiCacheStatus == ApiCacheStatus.UseCache)
                        {
                            jsonBody = runtimeContext.CachedResponseBody;
                        }
                        else
                        {
                            var invokeResult = Invoke(runtimeContext.ApiInstance, runtimeContext.ApiMethod, context, runtimeContext.EntityKey, out jsonBody);

                            if (runtimeContext.ApiCacheStatus == ApiCacheStatus.UpdateCache)
                            {
                                runtimeContext.ApiCacheContainer.Update(runtimeContext.ApiCacheIdentity, jsonBody);
                            }

                            PackageResponse(context, invokeResult, runtimeContext.OperationParameters, null, acceptEncoding, runtimeContext.IsVoid ?? false, settings: context.Settings);
                        }
                    }
                    catch (Exception invokeEx)
                    {
                        context.BaseException = invokeEx.Handle(new { Url = context.RawUrl, Method = context.HttpMethod });
                        throw context.BaseException;
                    }
                    finally
                    {
                        ApiTraceContext.Exit(context.BaseException?.Key);
                    }
                }
            }
            catch (Exception ex)
            {
                var apiTracking = context.Settings?.ApiTracking;
                context.BaseException = (ex as BaseException) ?? ex.Handle(new { Uri = context.Url.SafeToString() });

                (apiTracking ?? Framework.ApiTracking)?.LogException(context.BaseException.ToExceptionInfo(eventKey: context.ApiEvent?.Key.SafeToString()));

                if (context.ApiEvent != null)
                {
                    context.ApiEvent.ExceptionKey = context.BaseException.Key;
                }

                PackageResponse(context, null, null, context.BaseException, acceptEncoding, settings: context.Settings);
            }
            finally
            {
                if (context.Settings?.ApiTracking != null)
                {
                    var exitStamp = DateTime.UtcNow;
                    if (context.ApiEvent != null)
                    {
                        try
                        {
                            context.ApiEvent.ExitStamp = exitStamp;
                            context.Settings.ApiTracking.LogApiEvent(context.ApiEvent);
                        }
                        catch { }
                    }

                    if (ApiTraceContext.Root != null)
                    {
                        try
                        {
                            ApiTraceContext.Exit(context.BaseException?.Key, exitStamp);
                            context.Settings.ApiTracking.LogApiTraceLog(ApiTraceContext.GetCurrentTraceLog(true));
                        }
                        catch { }
                    }
                }

                Dispose();
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Invokes the specified method information.
 /// <remarks>
 /// Invoke action would regard to method parameter to use difference logic. Following steps show the IF-ELSE case. When it is hit, other would not go through.
 /// <list type="number"><item>
 /// If input parameter count is 0, invoke without parameter object.
 /// </item><item>
 /// If input parameter count is 1 and key is not empty or null, invoke using key.
 /// </item><item>
 /// If input parameter count is 1 and key is empty or null, invoke using key, try to get JSON object from request body and convert to object for invoke.
 /// </item><item>
 /// If input parameter count more than 1, try read JSON data to match parameters by name (ignore case) in root level, then invoke.
 /// </item></list></remarks></summary>
 protected virtual object Invoke(object instance, MethodInfo methodInfo, HttpApiContextContainer <TRequest, TResponse> context, string key, out string jsonBody)
 {
     return(InternalInvoke(instance, methodInfo, context.ReadRequestBody(), context.Url, key, out jsonBody));
 }