private ApiHandlerOutput Process(ApiInputHandler input) { string typeName = Business.Resource.GetType(input.Resource); if (string.IsNullOrWhiteSpace(typeName)) { throw new ApiNotFoundException(input.Resource); } bool canAccess = Business.Authorization.CanAccess(input.Resource, Context.Current.User); if (!canAccess) { logger.Warn($"Access denied for resource {input.Resource}"); throw new SecurityException(Messages.AccessDenied); } if (Business.Authorization.RequireToken(input.Resource)) { string token = input.Context.Request.Headers["ZestyApiToken"]; if (string.IsNullOrWhiteSpace(token)) { token = input.Context.Request.Query["t"]; } if (!Business.Authorization.IsValid(Context.Current.User.Id, input.Context.Session.Id, token)) { logger.Warn($"Invalid token for resource {input.Resource}"); throw new SecurityException(Messages.TokenMissing); } } ApiCacheItem cacheItem = ApiCache.Get(input); if (cacheItem != null) { logger.Info($"Output found in cache for request {input.Resource}"); return(cacheItem.Output); } else { ApiHandlerBase handler = InstanceHelper.Create <ApiHandlerBase>(typeName); ApiHandlerOutput output = handler.Process(input); if (output.CachePolicy == ApiCachePolicy.Enable) { cacheItem = new ApiCacheItem { Created = DateTime.Now, Output = output, Payload = input.Body, Resource = input.Resource }; ApiCache.Store(cacheItem); logger.Info($"Output stored in cache for request {input.Resource}"); } if (output.ResourceHistoryOutput != null && output.ResourceHistoryOutput.ResourceHistoryPolicy == ApiResourceHistoryPolicy.Save) { Business.History.Save(output.ResourceHistoryOutput.Item); } return(output); } }
public async Task Invoke(HttpContext context) { TimeKeeper timeKeeper = new TimeKeeper(); string contentType = null; string content = null; int statusCode = 200; try { LoadUser(context); string resourceName = context.Request.Path.Value; string body = new StreamReader(context.Request.Body).ReadToEndAsync().Result; logger.Info($"User: {Context.Current.User?.Username}"); logger.Info($"Resource: {resourceName}"); logger.Debug($"Body: {body}"); logger.Info($"Session ID: {context.Session.Id}"); logger.Info($"HTTP method: {context.Request.Method}"); ApiInputHandler input = new ApiInputHandler() { Body = body, Context = context, Resource = resourceName }; if (context.Request.Method == "OPTIONS") { //TODO improve this poor code :D contentType = ContentType.TextPlain; content = ":)"; } else { HandlerProcessor.Process(Settings.List("PreExecutionHandler"), context); ApiHandlerOutput output = Process(input); HandlerProcessor.Process(Settings.List("PostExecutionHandler"), context); if (output.Type == ApiHandlerOutputType.JSon) { contentType = ContentType.ApplicationJson; content = JsonHelper.Serialize(output.Output); } else if (output.Type == ApiHandlerOutputType.TextAsJson) { contentType = ContentType.ApplicationJson; content = output.Output as string; } else if (output.Type == ApiHandlerOutputType.Text) { contentType = ContentType.TextPlain; content = output.Output as string; } else { throw new Exception(Messages.WrongApiOutput); } } } #region catches catch (ApiInvalidArgumentException e) { logger.Error(e); statusCode = 501; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (ApiNotFoundException e) { logger.Error(e); statusCode = 404; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (ApiTokenExpiredException e) { logger.Error(e); statusCode = 401; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (ApiAccessDeniedException e) { logger.Error(e); statusCode = 401; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (MissingRequiredProperty e) { logger.Error(e); statusCode = 400; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (CustomJsonException e) { logger.Error(e); statusCode = 502; // TODO check this code contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (SecurityException e) { logger.Error(e); statusCode = 403; // TODO check this code contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } catch (Exception e) { logger.Error(e); statusCode = 500; contentType = ContentType.ApplicationJson; string message = propagateApplicationErrorInFault ? e.Message : Messages.GenericFailure; content = JsonHelper.Serialize(new { Message = message }); Trace.Write(new TraceItem() { Error = e.Message, Millis = timeKeeper.Stop().TotalMilliseconds }, context); } #endregion finally { logger.Debug($"ContentType: {contentType}"); logger.Debug($"Content: {content}"); logger.Info($"statusCode: {statusCode}"); context.Response.ContentType = contentType; context.Response.StatusCode = statusCode; await context.Response.WriteAsync(content); double ms = timeKeeper.Stop().TotalMilliseconds; Trace.Write(new TraceItem() { Millis = ms }, context); logger.Info($"Request completed in {ms} ms"); } }