/// <summary> /// Processes the route. /// </summary> /// <param name="context">The context.</param> /// <param name="doAuthentication">if set to <c>true</c> [do authentication].</param> /// <returns></returns> /// <exception cref="ResourceNotFoundException"> /// ResourceName /// or /// or /// </exception> internal virtual RuntimeContext ProcessRoute(HttpApiContextContainer <TRequest, TResponse> context, bool doAuthentication = true) { try { context.CheckNullObject(nameof(context)); var httpMethod = context.HttpMethod; var uri = context.Url; var rawFullUrl = string.Format("{0}: {1}", httpMethod, context.Url); var result = InitializeRuntimeContext(uri); result.CheckNullObjectAsInvalid("URL"); if (result.Version.Equals(ApiConstants.BuiltInFeatureVersionKeyword, StringComparison.OrdinalIgnoreCase)) { return(result); } if (string.IsNullOrWhiteSpace(result.ResourceName)) { throw new ResourceNotFoundException(rawFullUrl, nameof(result.ResourceName)); } RuntimeRoute runtimeRoute; var apiRouterIdentifier = new ApiRouteIdentifier(result.Realm, result.Version, result.ResourceName, httpMethod, result.Parameter1); if (!RestApiRoutePool.Routes.TryGetValue(apiRouterIdentifier, out runtimeRoute)) { apiRouterIdentifier = new ApiRouteIdentifier(result.Realm, result.Version, result.ResourceName, httpMethod, null); RestApiRoutePool.Routes.TryGetValue(apiRouterIdentifier, out runtimeRoute); } else { if (runtimeRoute != null && (!string.IsNullOrWhiteSpace(result.Parameter1) && !runtimeRoute.IsActionUsed)) { throw new ResourceNotFoundException(rawFullUrl); } } if (runtimeRoute == null) { throw new ResourceNotFoundException(rawFullUrl); } result.ApiRouterIdentifier = apiRouterIdentifier; // Override out parameters result.OperationParameters = runtimeRoute.OperationParameters ?? new RuntimeApiOperationParameters(); result.ApiMethod = runtimeRoute.ApiMethod; result.ApiInstance = runtimeRoute.ApiInstance; result.IsActionUsed = runtimeRoute.IsActionUsed; result.IsVoid = runtimeRoute.IsVoid; context.Settings = result.Settings = runtimeRoute.Setting ?? RestApiSettingPool.DefaultRestApiSettings; result.OmitApiEvent = runtimeRoute.OmitApiTracking?.Omit(ApiTrackingType.Event) ?? false; if (runtimeRoute.ApiCacheAttribute != null) { result.ApiCacheIdentity = runtimeRoute.ApiRouteIdentifier.Clone() as ApiRouteIdentifier; if (runtimeRoute.ApiCacheAttribute.CacheParameter.CachedByParameterizedIdentity) { result.ApiCacheIdentity.SetParameterizedIdentifier(uri.ToQueryString()); } result.ApiCacheContainer = runtimeRoute.ApiCacheContainer; if (result.ApiCacheContainer != null) { string cachedResponseBody; if (result.ApiCacheContainer.GetCacheResult(result.ApiCacheIdentity, out cachedResponseBody)) { result.CachedResponseBody = cachedResponseBody; result.ApiCacheStatus = ApiCacheStatus.UseCache; } else { result.ApiCacheStatus = ApiCacheStatus.UpdateCache; } } else { result.ApiCacheStatus = ApiCacheStatus.NoCache; } } // Fill basic context info. var userAgentHeaderKey = context.Settings?.OriginalUserAgentHeaderKey; var token = context.TryGetRequestHeader((context.Settings?.TokenHeaderKey).SafeToString(HttpConstants.HttpHeader.TOKEN)); ContextHelper.ApiContext.IndicatedOperator = context.TryGetRequestHeader(HttpConstants.HttpHeader.OPERATOR); ContextHelper.ConsistContext( // TOKEN 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()), apiRouterIdentifier.ToApiUniqueIdentifier() ); string userIdentifier = ContextHelper.ApiContext.CurrentCredential?.Name.SafeToString(token); var authenticationException = doAuthentication ? Authorize(runtimeRoute, ContextHelper.ApiContext) : null; if (authenticationException != null) { throw authenticationException.Handle(new { result.ApiMethod.Name, token }); } return(result); } catch (Exception ex) { throw ex.Handle(); } }
/// <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(); } }
/// <summary> /// Processes the built in feature. /// </summary> /// <param name="context">The context.</param> /// <param name="runtimeContext">The runtime context.</param> /// <param name="isLocalhost">if set to <c>true</c> [is localhost].</param> /// <param name="contentType">Type of the content.</param> /// <returns></returns> protected virtual object ProcessBuiltInFeature(HttpApiContextContainer <TRequest, TResponse> context, RuntimeContext runtimeContext, bool isLocalhost, out string contentType) { object result = null; contentType = HttpConstants.ContentType.Json; switch (runtimeContext?.ResourceName.SafeToLower()) { case "server": result = Framework.AboutService(); break; case "psk": //public secured key result = Framework.AboutService(); break; case "configuration": result = isLocalhost ? Framework.ConfigurationValues : localhostTip as object; break; case "machine": result = SystemManagementExtension.GetMachineHealth(); break; case "cache": result = CacheRealm.GetSummary(); break; case "clearmemorycache": if (isLocalhost) { CacheRealm.ClearAll(); result = "Done."; } else { result = "This API is available at localhost machine."; } break; case "gravity": result = //Gravity.GravityShell.Current?.Info; "<Retired>"; break; case "i18n": result = Framework.GetGlobalResourceAvailableCultureInfo() ?? new Collection <CultureInfo>(); break; case "mirror": var apiContext = ContextHelper.ApiContext; var headers = new Dictionary <string, string>(); foreach (var key in context.RequestAllHeaderKeys) { headers.Add(key, context.TryGetRequestHeader(key)); } result = new { RawUrl = context.RawUrl, HttpMethod = context.HttpMethod, Headers = headers, UserAgent = apiContext.UserAgent, IpAddress = apiContext.IpAddress, CultureCode = apiContext.CultureCode }; break; case "assemblyhash": result = EnvironmentCore.GetAssemblyHash(); break; case "dll": var dllName = context.QueryString.Get("name"); if (!string.IsNullOrWhiteSpace(dllName) && context.HttpMethod.MeaningfulEquals(HttpConstants.HttpMethod.Post, StringComparison.OrdinalIgnoreCase)) { try { var dllPath = Path.Combine(EnvironmentCore.ApplicationBaseDirectory, dllName + ".dll"); if (File.Exists(dllPath)) { result = File.ReadAllBytes(dllPath); contentType = HttpConstants.ContentType.BinaryDefault; } } catch { } } break; default: break; } return(result); }