public void ProcessRequest(HttpContext context) { string urlPath = context.Request.AppRelativeCurrentExecutionFilePath.Substring("~/api/".Length) + context.Request.PathInfo; /* * */ JsonRequest request = new JsonRequest(); request.ExecutionId = Guid.NewGuid(); request.Rule = urlPath.Replace("/", "."); request.MomentStart = DateTime.UtcNow; /* * */ using (var sr = new StreamReader(HttpContext.Current.Request.InputStream)) { sr.BaseStream.Seek(0, SeekOrigin.Begin); request.Message = sr.ReadToEnd(); } /* * */ RuleRunner rr = new RuleRunner(); IRule rule = rr.Get(request.Rule); if (rule == null) { context.Response.StatusCode = 404; context.Response.End(); } /* * */ object oreq = JsonConvert.DeserializeObject(request.Message, rule.RequestType); /* * */ JsonResponse response; try { object oresp = rr.Run(rule, oreq); response = new JsonResponse(); response.IsFault = false; response.Message = JsonConvert.SerializeObject(oresp); } catch (ActorException) { // TODO response = new JsonResponse(); response.IsFault = false; response.Message = "{}"; } catch (Exception) { // TODO response = new JsonResponse(); response.IsFault = true; response.Message = "{}"; } /* * */ context.Response.TrySkipIisCustomErrors = true; context.Response.StatusCode = 200; context.Response.CacheControl = "private"; context.Response.ContentType = "application/json; charset=utf-8"; context.Response.Headers.Add("X-Hafnium-ExecutionId", request.ExecutionId.ToString("D")); context.Response.Headers.Add("X-Hafnium-MomentStart", request.MomentStart.ToString("s")); context.Response.Headers.Add("X-Hafnium-MomentEnd", DateTime.UtcNow.ToString("s")); context.Response.Write(response.Message); context.Response.End(); }
public void ProcessRequest(HttpContext context) { #region Validations if (context == null) { throw new ArgumentNullException("context"); } #endregion /* * */ ExecutionHeader execution = new ExecutionHeader(); execution.ExecutionId = Guid.NewGuid(); execution.MomentStart = DateTime.UtcNow; /* * */ SoapRequest request = null; if (context.Request.Headers["SOAPAction"] != null) { request = new SoapRequest(); request.Version = SoapVersion.Soap11; request.SoapAction = context.Request.Headers["SOAPAction"]; request.SoapAction = request.SoapAction.Substring(1, request.SoapAction.Length - 2); } else { var values = context.Request.ContentType .Split(';') .Select(s => { var p = s.Split(new char[] { '=' }, 2); if (p.Length == 1) { return new { Key = "content-type", Value = p[0] } } ; else { return new { Key = p[0], Value = p[1] } }; }).ToList(); var contentType = values.FirstOrDefault(x => x.Key == "content-type"); var action = values.FirstOrDefault(x => x.Key == "action"); if (contentType?.Value == "application/soap+xml" && action != null) { request = new SoapRequest(); request.Version = SoapVersion.Soap12; request.SoapAction = action.Value.Substring(1, action.Value.Length - 2); } } if (request == null) { ActorException error = new WebException(ER.Soap_RequestNotSoap); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } /* * Derive the rule being invoked, based on the URL of the request. */ if (request.SoapAction.StartsWith(WebServicesConfiguration.Current.Namespace) == false) { ActorException error = new WebException(ER.Soap_ActionUnsupported, request.SoapAction, WebServicesConfiguration.Current.Namespace); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } string ruleName = request.SoapAction.Substring(WebServicesConfiguration.Current.Namespace.Length).Replace("/", "."); /* * */ using (var sr = new StreamReader(HttpContext.Current.Request.InputStream)) { sr.BaseStream.Seek(0, SeekOrigin.Begin); request.Message = sr.ReadToEnd(); } /* * Service NS - derived from the name of the rule :) */ string[] parts = ruleName.Split('.'); string serviceNs = string.Join("/", parts.Take(parts.Length - 2)) + "/"; /* * */ RuleRunner rr = new RuleRunner(); IRule rule = rr.Get(ruleName); if (rule == null) { ActorException error = new WebException(ER.Soap_ActionUnknown, request.SoapAction); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } /* * */ XNamespace soapNs; if (request.Version == SoapVersion.Soap11) { soapNs = "http://schemas.xmlsoap.org/soap/envelope/"; } else { soapNs = "http://www.w3.org/2003/05/soap-envelope"; } XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); manager.AddNamespace("soap", soapNs.NamespaceName); /* * */ XDocument requestDoc; try { using (StringReader sr = new StringReader(request.Message)) { requestDoc = XDocument.Load(sr); } } catch (XmlException ex) { ActorException error = new WebException(ER.Soap_RequestNotXml, ex); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } XElement element = requestDoc.XPathSelectElement(" /soap:Envelope/soap:Body/*[ 1 ] ", manager); if (element == null) { ActorException error = new WebException(ER.Soap_BodyNotFound); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } /* * */ object oreq; XmlSerializer der = XmlSerializerFor(rule.RequestType, serviceNs); try { oreq = der.Deserialize(element.CreateReader()); } catch (InvalidOperationException ex) { ActorException error = new WebException(ER.Soap_RequestInvalid, ex, rule.Name, rule.RequestType.FullName); var fault = ToFault(request.Version, execution, error); ResponseEmit(context, fault); return; } /* * */ SoapResponse response; try { object oresp; oresp = rr.Run(rule, oreq); response = ToResponse(request.Version, execution, oresp, serviceNs); } catch (ActorException ex) { response = ToFault(request.Version, execution, ex); } catch (Exception ex) { ActorException aex = new WebException(ER.Soap_UnhandledException, ex); response = ToFault(request.Version, execution, aex); } /* * */ ResponseEmit(context, response); return; }