public object ExecutePath( string httpMethod, string pathInfo, Dictionary <string, string> queryString, Dictionary <string, string> formData, string requestBody) { var contentType = (formData != null && formData.Count > 0) ? MimeTypes.FormUrlEncoded : requestBody != null ? MimeTypes.Json : null; var httpReq = new MockHttpRequest( nameof(MockHttpRequest), httpMethod, contentType, pathInfo, queryString.ToNameValueCollection(), requestBody == null ? null : Encoding.UTF8.GetBytes(requestBody).InMemoryStream(), formData.ToNameValueCollection() ); var httpHandler = (IRequestHttpHandler)GetHandler(httpReq); httpReq.OperationName = httpHandler.RequestName; var request = httpHandler.CreateRequestAsync(httpReq, httpHandler.RequestName).Result; object response; try { response = httpHandler.GetResponseAsync(httpReq, request).Result; } catch (Exception ex) { response = DtoUtils.CreateErrorResponse(request, ex); } if (response is IHttpResult httpRes) { if (httpRes is IHttpError httpError) { throw new WebServiceException(httpError.Message) { StatusCode = httpError.Status, ResponseDto = httpError.Response }; } var hasResponseStatus = httpRes.Response as IHasResponseStatus; var status = hasResponseStatus?.ResponseStatus; if (status != null && !status.ErrorCode.IsNullOrEmpty()) { throw new WebServiceException(status.Message) { StatusCode = (int)HttpStatusCode.InternalServerError, ResponseDto = httpRes.Response, }; } return(httpRes.Response); } return(response); }
/// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> public override void Configure(Container container) { //Set JSON web services to return idiomatic JSON camelCase properties ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; // overrides to default ServiceStack configuration SetConfig(new HostConfig { EnableFeatures = Feature.All, DefaultContentType = "application/json", DebugMode = true, // show stack traces WriteErrorsToResponse = true, AdminAuthSecret = "A0verrid3" // TODO: drop this in Production }); Plugins.Add(new CorsFeature( allowedOrigins: "*", allowedHeaders: "Content-Type, Authorization", allowCredentials: true )); Plugins.Add(new RequestLogsFeature { }); Plugins.Add(new SwaggerFeature { DisableAutoDtoInBodyParam = false, }); // return dates like this: 2012-08-21T11:02:32.0449348-04:00 ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601; // make sure default connection profile exists var custData = System.Configuration.ConfigurationManager.ConnectionStrings["dbCustData"].ConnectionString; var data = System.Configuration.ConfigurationManager.ConnectionStrings["dbData"].ConnectionString; // TODO: setup correct db... We use SQL Server var cp = "Data Source=localhost;Initial Catalog=AuthDb;User ID=sa;Password=123;Connect Timeout=3600"; //Register IOC dependencies container.Register <DbContext>(ctx => new DbContext(cp)).ReusedWithin(ReuseScope.Request); // handle exceptions in services this.ServiceExceptionHandlers.Add((httpReq, requestDto, ex) => { return(DtoUtils.CreateErrorResponse(requestDto, ex)); }); // handle exceptions not in services this.UncaughtExceptionHandlers.Add((httpReq, httpResp, operationName, ex) => { // TODO: Figure out what changed between ServiceStack -Version 4.0.33 -> 4.0.62 as this throws an error as HttpResponse has already been submitted //httpResp.Write("Error: {0}: {1}".Fmt(ex.GetType().Name, ex.Message)); httpResp.EndRequest(skipHeaders: true); // FUTURE: perhaps save errors to db }); this.GlobalRequestFilters.Add((req, res, dto) => { Stopwatch sw = new Stopwatch(); sw.Start(); req.Items.Add("StopWatch", sw); }); this.GlobalResponseFilters.Add((req, res, dto) => { if (req.Items.ContainsKey("StopWatch")) { var sw = req.Items["StopWatch"] as Stopwatch; sw.Stop(); } ; }); /* TODO: determine which db to house auth info in * for now, dump into CustData* (NA as default) */ ConfigureAuth(container, cp); }
private static async Task RequestFilterAsync(IRequest req, IResponse res, object requestDto, bool treatInfoAndWarningsAsErrors) { var validator = ValidatorCache.GetValidator(req, requestDto.GetType()); if (validator == null) { return; } using (validator as IDisposable) { try { var validationResult = await Validate(validator, req, requestDto); if (treatInfoAndWarningsAsErrors && validationResult.IsValid) { return; } if (!treatInfoAndWarningsAsErrors && (validationResult.IsValid || validationResult.Errors.All(v => v.Severity != Severity.Error))) { return; } var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationResult.ToException()) ?? DtoUtils.CreateErrorResponse(requestDto, validationResult.ToErrorResult()); var autoBatchIndex = req.GetItem(Keywords.AutoBatchIndex)?.ToString(); if (autoBatchIndex != null) { var responseStatus = errorResponse.GetResponseStatus(); if (responseStatus != null) { if (responseStatus.Meta == null) { responseStatus.Meta = new Dictionary <string, string>(); } responseStatus.Meta[Keywords.AutoBatchIndex] = autoBatchIndex; } } var validationFeature = HostContext.GetPlugin <ValidationFeature>(); if (validationFeature?.ErrorResponseFilter != null) { errorResponse = validationFeature.ErrorResponseFilter(validationResult, errorResponse); } await res.WriteToResponse(req, errorResponse); } catch (Exception ex) { var validationEx = ex.UnwrapIfSingleException(); var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationEx) ?? DtoUtils.CreateErrorResponse(requestDto, validationEx); await res.WriteToResponse(req, errorResponse); } } }
public void SerializeToStream(IRequest req, object response, IResponse res) { var httpResult = req.GetItem("HttpResult") as IHttpResult; if (httpResult != null && httpResult.Headers.ContainsKey(HttpHeaders.Location) && httpResult.StatusCode != System.Net.HttpStatusCode.Created) { return; } try { if (res.StatusCode >= 400) { var responseStatus = response.GetResponseStatus(); req.Items[ErrorStatusKey] = responseStatus; } if (response is CompressedResult) { if (res.Dto != null) { response = res.Dto; } else { throw new ArgumentException("Cannot use Cached Result as ViewModel"); } } if (AppHost.ViewEngines.Any(x => x.ProcessRequest(req, res, response))) { return; } } catch (Exception ex) { if (res.StatusCode < 400) { throw; } //If there was an exception trying to render a Error with a View, //It can't handle errors so just write it out here. response = DtoUtils.CreateErrorResponse(req.Dto, ex); } //Handle Exceptions returning string if (req.ResponseContentType == MimeTypes.PlainText) { req.ResponseContentType = MimeTypes.Html; res.ContentType = MimeTypes.Html; } if (req.ResponseContentType != MimeTypes.Html && req.ResponseContentType != MimeTypes.JsonReport) { return; } var dto = response.GetDto(); var html = dto as string; if (html == null) { // Serialize then escape any potential script tags to avoid XSS when displaying as HTML var json = JsonDataContractSerializer.Instance.SerializeToString(dto) ?? "null"; json = json.Replace("<", "<").Replace(">", ">"); var url = req.ResolveAbsoluteUrl() .Replace("format=html", "") .Replace("format=shtm", "") .TrimEnd('?', '&'); url += url.Contains("?") ? "&" : "?"; var now = DateTime.UtcNow; var requestName = req.OperationName ?? dto.GetType().GetOperationName(); html = HtmlTemplates.GetHtmlFormatTemplate() .Replace("${Dto}", json) .Replace("${Title}", string.Format(TitleFormat, requestName, now)) .Replace("${MvcIncludes}", MiniProfiler.Profiler.RenderIncludes().ToString()) .Replace("${Header}", string.Format(HtmlTitleFormat, requestName, now)) .Replace("${ServiceUrl}", url) .Replace("${Humanize}", Humanize.ToString().ToLower()); } var utf8Bytes = html.ToUtf8Bytes(); res.OutputStream.Write(utf8Bytes, 0, utf8Bytes.Length); }
public override void Configure(Container container) { //Set JSON web services to return idiomatic JSON camelCase properties JsConfig.EmitCamelCaseNames = true; JsConfig.ThrowOnDeserializationError = true; JsConfig.DateHandler = JsonDateHandler.ISO8601; JsConfig <Guid> .SerializeFn = guid => guid.ToString("D"); JsConfig <Guid?> .SerializeFn = nullableGuid => nullableGuid.HasValue ? nullableGuid.Value.ToString("D") : string.Empty; Plugins.Add(new CorsFeature(ConfigurationManager.AppSettings["webSiteDomain"], "GET, POST, PUT, DELETE, OPTIONS", "Content-Type")); //Handles Request and closes Response after emitting global HTTP Headers var emitGlobalHeadersHandler = new CustomActionHandler( (httpReq, httpRes) => httpRes.EndRequest()); SetConfig(new EndpointHostConfig { RawHttpHandlers = { httpReq => httpReq.HttpMethod == HttpMethods.Options ? emitGlobalHeadersHandler : null } #if !DEBUG , DebugMode = false // Remove stacktrace inside the response #endif }); container.Register(c => new Database("localDB")).ReusedWithin(ReuseScope.Request); container.RegisterAutoWired <Repository <ErrorLog> >().ReusedWithin(ReuseScope.Request); container.RegisterAutoWired <LessonRepository>().ReusedWithin(ReuseScope.Request); container.RegisterAutoWired <UserRepository>().ReusedWithin(ReuseScope.Request); container.RegisterAutoWired <StudentLessonAnswerRepository>().ReusedWithin(ReuseScope.Request); container.RegisterAutoWired <GradeRepository>().ReusedWithin(ReuseScope.Request); ServiceExceptionHandler = (req, request, exception) => { var errorLog = new ErrorLog { Application = "MetacognitiveTutor.Api", Message = exception.Message, StackTrace = exception.StackTrace }; container.Resolve <Repository <ErrorLog> >().Add(errorLog); return(DtoUtils.CreateErrorResponse(request, exception, new ResponseStatus(HttpStatusCode.InternalServerError.ToString()))); }; //Handle Unhandled Exceptions occurring outside of Services //E.g. Exceptions during Request binding or in filters: ExceptionHandler = (req, res, operationName, ex) => { var errorLog = new ErrorLog { Application = "MetacognitiveTutor.Api", Message = ex.Message, StackTrace = ex.StackTrace }; container.Resolve <Repository <ErrorLog> >().Add(errorLog); res.Write("Error: {0}: {1}".Fmt(ex.GetType().Name, ex.Message)); res.EndRequest(skipHeaders: true); }; //Enable Authentication //ConfigureAuth(container); }
public async Task SerializeToStreamAsync(IRequest req, object response, Stream outputStream) { var res = req.Response; if (req.GetItem("HttpResult") is IHttpResult httpResult && httpResult.Headers.ContainsKey(HttpHeaders.Location) && httpResult.StatusCode != System.Net.HttpStatusCode.Created) { return; } try { if (res.StatusCode >= 400) { var responseStatus = response.GetResponseStatus(); req.Items[ErrorStatusKey] = responseStatus; } if (response is CompressedResult) { if (res.Dto != null) { response = res.Dto; } else { throw new ArgumentException("Cannot use Cached Result as ViewModel"); } } foreach (var viewEngine in ViewEngines) { var handled = await viewEngine.ProcessRequestAsync(req, response, outputStream); if (handled) { return; } } } catch (Exception ex) { if (res.StatusCode < 400) { throw; } //If there was an exception trying to render a Error with a View, //It can't handle errors so just write it out here. response = DtoUtils.CreateErrorResponse(req.Dto, ex); } //Handle Exceptions returning string if (req.ResponseContentType == MimeTypes.PlainText) { req.ResponseContentType = MimeTypes.Html; res.ContentType = MimeTypes.Html; } if (req.ResponseContentType != MimeTypes.Html && req.ResponseContentType != MimeTypes.JsonReport) { return; } var dto = response.GetDto(); if (!(dto is string html)) { // Serialize then escape any potential script tags to avoid XSS when displaying as HTML var json = JsonDataContractSerializer.Instance.SerializeToString(dto) ?? "null"; json = json.Replace("<", "<").Replace(">", ">"); var url = req.ResolveAbsoluteUrl(); var index = url.IndexOf("?"); var formatUrl = index != -1 ? url.Substring(0, index + 1) : url + "?"; foreach (var key in req.QueryString.AllKeys) { if (key == Keywords.Format) { continue; } formatUrl += (key.IsNullOrEmpty() ? "" : key + "=") + req.QueryString[key] + "&"; } var now = DateTime.Now; var requestName = req.OperationName ?? dto.GetType().GetOperationName(); html = HtmlTemplates.GetHtmlFormatTemplate() .Replace("${Dto}", json) .Replace("${Title}", string.Format(TitleFormat, requestName, now)) .Replace("${MvcIncludes}", MiniProfiler.Profiler.RenderIncludes()?.ToString()) .Replace("${Header}", string.Format(HtmlTitleFormat, requestName, now)) .Replace("${ServiceUrl}", req.AbsoluteUri) .Replace("${FormatUrl}", formatUrl) .Replace("${Humanize}", Humanize.ToString().ToLower()); } var utf8Bytes = html.ToUtf8Bytes(); await outputStream.WriteAsync(utf8Bytes, 0, utf8Bytes.Length); }
public override object HandleException(IRequest request, T requestDto, System.Exception ex) { return(DtoUtils.CreateErrorResponse(requestDto, ex)); }
public async Task SerializeToStreamAsync(IRequest req, object response, Stream outputStream) { var res = req.Response; if (req.GetItem("HttpResult") is IHttpResult httpResult && httpResult.Headers.ContainsKey(HttpHeaders.Location) && httpResult.StatusCode != System.Net.HttpStatusCode.Created) { return; } try { if (res.StatusCode >= 400) { var responseStatus = response.GetResponseStatus(); req.Items[Keywords.ErrorStatus] = responseStatus; } if (response is CompressedResult) { if (res.Dto != null) { response = res.Dto; } else { throw new ArgumentException("Cannot use Cached Result as ViewModel"); } } foreach (var viewEngine in AppHost.ViewEngines) { var handled = await viewEngine.ProcessRequestAsync(req, response, outputStream); if (handled) { return; } } } catch (Exception ex) { if (res.StatusCode < 400) { throw; } //If there was an exception trying to render a Error with a View, //It can't handle errors so just write it out here. response = DtoUtils.CreateErrorResponse(req.Dto, ex); } //Handle Exceptions returning string if (req.ResponseContentType == MimeTypes.PlainText) { req.ResponseContentType = MimeTypes.Html; res.ContentType = MimeTypes.Html; } if (req.ResponseContentType != MimeTypes.Html && req.ResponseContentType != MimeTypes.JsonReport) { return; } var dto = response.GetDto(); if (!(dto is string html)) { // Serialize then escape any potential script tags to avoid XSS when displaying as HTML var json = JsonDataContractSerializer.Instance.SerializeToString(dto) ?? "null"; json = json.HtmlEncodeLite(); var url = req.ResolveAbsoluteUrl() .Replace("format=html", "") .Replace("format=shtm", "") .TrimEnd('?', '&') .HtmlEncode(); url += url.Contains("?") ? "&" : "?"; var now = DateTime.UtcNow; var requestName = req.OperationName ?? dto.GetType().GetOperationName(); html = (ResolveTemplate?.Invoke(req) ?? Templates.HtmlTemplates.GetHtmlFormatTemplate()) .Replace("${Dto}", json) .Replace("${BaseUrl}", req.GetBaseUrl().TrimEnd('/')) .Replace("${Title}", string.Format(TitleFormat, requestName, now)) .Replace("${MvcIncludes}", MiniProfiler.Profiler.RenderIncludes().ToString()) .Replace("${Header}", string.Format(HtmlTitleFormat, requestName, now)) .Replace("${ServiceUrl}", url) .Replace("${Humanize}", Humanize.ToString().ToLower()) .Replace("${AuthRedirect}", req.ResolveAbsoluteUrl(AppHost.GetPlugin <AuthFeature>()?.HtmlRedirect)) .Replace("${AllowOrigins}", AppHost.GetPlugin <CorsFeature>()?.AllowOriginWhitelist?.Join(";")); } await((ServiceStackHost)AppHost).WriteAutoHtmlResponseAsync(req, response, html, outputStream); }
public ResponseStatus Parse(ValidationError validationException) { return(DtoUtils.CreateErrorResponse(validationException.ErrorCode, validationException.Message, validationException.Violations)); }
public ResponseStatus Parse(ValidationErrorResult validationResult) { return(validationResult.IsValid ? DtoUtils.CreateSuccessResponse(validationResult.SuccessMessage) : DtoUtils.CreateErrorResponse(validationResult.ErrorCode, validationResult.ErrorMessage, validationResult.Errors)); }
public override Task <object> HandleExceptionAsync(IRequest request, T requestDto, System.Exception ex) { return(DtoUtils.CreateErrorResponse(requestDto, ex).InTask()); }
private static async Task RequestFilterAsync(IRequest req, IResponse res, object requestDto, bool treatInfoAndWarningsAsErrors) { var requestType = requestDto.GetType(); await Validators.AssertTypeValidatorsAsync(req, requestDto, requestType); var validator = ValidatorCache.GetValidator(req, requestType); if (validator == null) { return; } using (validator as IDisposable) { if (validator is IHasTypeValidators hasTypeValidators && hasTypeValidators.TypeValidators.Count > 0) { foreach (var scriptValidator in hasTypeValidators.TypeValidators) { await scriptValidator.ThrowIfNotValidAsync(requestDto, req); } } try { if (req.Verb == HttpMethods.Patch) { // Ignore property rules for AutoCrud Patch operations with default values that aren't reset (which are ignored) if (validator is IServiceStackValidator ssValidator && requestDto is ICrud && requestType.IsOrHasGenericInterfaceTypeOf(typeof(IPatchDb <>))) { var typeProperties = TypeProperties.Get(requestType); var propsWithDefaultValues = new HashSet <string>(); var resetFields = GetResetFields(req.GetParam(Keywords.reset))?.ToSet(StringComparer.OrdinalIgnoreCase) ?? TypeConstants <string> .EmptyHashSet; foreach (var entry in typeProperties.PropertyMap) { if (entry.Value.PublicGetter == null || resetFields.Contains(entry.Key)) { continue; } var defaultValue = entry.Value.PropertyInfo.PropertyType.GetDefaultValue(); var propValue = entry.Value.PublicGetter(requestDto); if (propValue == null || propValue.Equals(defaultValue)) { propsWithDefaultValues.Add(entry.Key); } } if (propsWithDefaultValues.Count > 0) { ssValidator.RemovePropertyRules(rule => propsWithDefaultValues.Contains(rule.PropertyName)); } } } var validationResult = await validator.ValidateAsync(req, requestDto); if (treatInfoAndWarningsAsErrors && validationResult.IsValid) { return; } if (!treatInfoAndWarningsAsErrors && (validationResult.IsValid || validationResult.Errors.All(v => v.Severity != Severity.Error))) { return; } var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationResult.ToException()) ?? DtoUtils.CreateErrorResponse(requestDto, validationResult.ToErrorResult()); var autoBatchIndex = req.GetItem(Keywords.AutoBatchIndex)?.ToString(); if (autoBatchIndex != null) { var responseStatus = errorResponse.GetResponseStatus(); if (responseStatus != null) { if (responseStatus.Meta == null) { responseStatus.Meta = new Dictionary <string, string>(); } responseStatus.Meta[Keywords.AutoBatchIndex] = autoBatchIndex; } } var validationFeature = HostContext.GetPlugin <ValidationFeature>(); if (validationFeature?.ErrorResponseFilter != null) { errorResponse = validationFeature.ErrorResponseFilter(req, validationResult, errorResponse); } await res.WriteToResponse(req, errorResponse); } catch (Exception ex) { var validationEx = ex.UnwrapIfSingleException(); var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationEx) ?? DtoUtils.CreateErrorResponse(requestDto, validationEx); await res.WriteToResponse(req, errorResponse); } } }
/// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> public override void Configure(Container container) { //Handle Exceptions occurring in Services: this.ServiceExceptionHandlers.Add((httpReq, request, exception) => { // Log your exceptions here //... // Call the default exception handler or prepare your own custom response return(DtoUtils.CreateErrorResponse(request, exception)); }); // Handle Unhandled Exceptions occurring outside of Services // E.g. in Request binding or filters: //Handle Unhandled Exceptions occurring outside of Services //E.g. Exceptions during Request binding or in filters: this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) => { res.Write("Error: {0}: {1}".Fmt(ex.GetType().Name, ex.Message)); res.EndRequest(skipHeaders: true); }); //Config examples //this.Plugins.Add(new PostmanFeature()); //this.Plugins.Add(new CorsFeature()); // Handle Multiple Providers here. One per service. var dbProvider = ConfigurationManager.AppSettings.Get("DatabaseProvider"); if (dbProvider == "MySQL") { var connectionString = ConfigurationManager.ConnectionStrings["Database_MySQL"].ConnectionString; var dbFactory = new OrmLiteConnectionFactory( connectionString, ServiceStack.OrmLite.MySqlDialect.Provider); container.Register <IDbConnectionFactory>(c => dbFactory); } else if (dbProvider == "SqlServer") { var connectionString = ConfigurationManager.ConnectionStrings["Database_SQLServer"].ConnectionString; var dbFactory = new OrmLiteConnectionFactory( connectionString, ServiceStack.OrmLite.SqlServerDialect.Provider); container.Register <IDbConnectionFactory>(c => dbFactory); } var queueProvider = ConfigurationManager.AppSettings.Get("QueueProvider"); if (queueProvider == "SQS") { var awsAccessKey = ConfigurationManager.AppSettings.Get("AwsAccessKey"); var awsSecretKey = ConfigurationManager.AppSettings.Get("AwsSecretKey"); var awsRegionEndpoint = ConfigurationManager.AppSettings.Get("AwsRegionEndpoint"); var region = RegionEndpoint.GetBySystemName(awsRegionEndpoint); var queueUrl = ConfigurationManager.AppSettings.Get("QueueUrl"); container.Register <IMessageService>(c => new SqsMqServer( awsAccessKey, awsSecretKey, region) { DisableBuffering = true }); var mqServer = container.Resolve <IMessageService>(); mqServer.Start(); } else if (queueProvider == "Redis") { //Message Queueing var redisFactory = new PooledRedisClientManager("localhost:6379"); container.Register <IRedisClientsManager>(redisFactory); var mqHost = new RedisMqServer(redisFactory, retryCount: 2); mqHost.Start(); } }
public static async Task RequestFilterAsync(IRequest req, IResponse res, object requestDto) { var validator = ValidatorCache.GetValidator(req, requestDto.GetType()); var ruleSet = req.Verb; if (validator == null) { return; } try { ValidationResult validationResult; if (validator.HasAsyncValidators(ruleSet)) { validationResult = await validator.ValidateAsync( new ValidationContext(requestDto, null, new MultiRuleSetValidatorSelector(ruleSet)) { Request = req }); } else { validationResult = validator.Validate( new ValidationContext(requestDto, null, new MultiRuleSetValidatorSelector(ruleSet)) { Request = req }); } if (validationResult.IsValid) { return; } var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationResult.ToException()) ?? DtoUtils.CreateErrorResponse(requestDto, validationResult.ToErrorResult()); var validationFeature = HostContext.GetPlugin <ValidationFeature>(); if (validationFeature?.ErrorResponseFilter != null) { errorResponse = validationFeature.ErrorResponseFilter(validationResult, errorResponse); } await res.WriteToResponse(req, errorResponse); } catch (Exception ex) { var validationEx = ex.UnwrapIfSingleException(); var errorResponse = await HostContext.RaiseServiceException(req, requestDto, validationEx) ?? DtoUtils.CreateErrorResponse(requestDto, validationEx); await res.WriteToResponse(req, errorResponse); } finally { using (validator as IDisposable) { } } }
#pragma warning disable CS0672 public override Task <object> HandleExceptionAsync(IRequest req, T requestDto, System.Exception ex) #pragma warning restore CS0672 { return(DtoUtils.CreateErrorResponse(requestDto, ex).InTask()); }