Example #1
0
        public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher,
                                    ICertificateLocator certificateLocator,
                                    ILog log,
                                    Func <string, ReachabilityCheck, IMultiEnvironmentServiceDiscovery> serviceDiscoveryFactory,
                                    Func <DiscoveryConfig> getConfig,
                                    JsonExceptionSerializer exceptionSerializer)
        {
            EventPublisher     = eventPublisher;
            CertificateLocator = certificateLocator;

            Log = log;

            ServiceName         = serviceName;
            GetDiscoveryConfig  = getConfig;
            ExceptionSerializer = exceptionSerializer;

            var metricsContext = Metric.Context(METRICS_CONTEXT_NAME).Context(ServiceName);

            _serializationTime   = metricsContext.Timer("Serialization", Unit.Calls);
            _deserializationTime = metricsContext.Timer("Deserialization", Unit.Calls);
            _roundtripTime       = metricsContext.Timer("Roundtrip", Unit.Calls);

            _successCounter              = metricsContext.Counter("Success", Unit.Calls);
            _failureCounter              = metricsContext.Counter("Failed", Unit.Calls);
            _hostFailureCounter          = metricsContext.Counter("HostFailure", Unit.Calls);
            _applicationExceptionCounter = metricsContext.Counter("ApplicationException", Unit.Calls);

            ServiceDiscovery = serviceDiscoveryFactory(serviceName, ValidateReachability);
        }
Example #2
0
        public HttpServiceListener(IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition,
                                   ICertificateLocator certificateLocator, ILog log, IEventPublisher <ServiceCallEvent> eventPublisher,
                                   IEnumerable <ICustomEndpoint> customEndpoints,
                                   JsonExceptionSerializer exceptionSerializer,
                                   ServiceSchema serviceSchema,
                                   Func <LoadShedding> loadSheddingConfig,
                                   IServerRequestPublisher serverRequestPublisher)

        {
            ServiceSchema             = serviceSchema;
            _serverRequestPublisher   = serverRequestPublisher;
            ServiceEndPointDefinition = serviceEndPointDefinition;
            Worker              = worker;
            Activator           = activator;
            Log                 = log;
            EventPublisher      = eventPublisher;
            CustomEndpoints     = customEndpoints.ToArray();
            ExceptionSerializer = exceptionSerializer;
            LoadSheddingConfig  = loadSheddingConfig;

            if (serviceEndPointDefinition.UseSecureChannel)
            {
                ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate();
            }

            var urlPrefixTemplate = ServiceEndPointDefinition.UseSecureChannel ? "https://+:{0}/" : "http://+:{0}/";

            Prefix = string.Format(urlPrefixTemplate, ServiceEndPointDefinition.HttpPort);

            Listener = new HttpListener
            {
                IgnoreWriteExceptions = true,
                Prefixes = { Prefix }
            };
        }
        public HttpServiceListener(
            IActivator activator,
            IWorker worker,
            IServiceEndPointDefinition serviceEndPointDefinition,
            ICertificateLocator certificateLocator,
            ILog log,
            IEnumerable <ICustomEndpoint> customEndpoints,
            IEnvironment environment,
            JsonExceptionSerializer exceptionSerializer,
            ServiceSchema serviceSchema,
            Func <LoadShedding> loadSheddingConfig,
            IServerRequestPublisher serverRequestPublisher,
            CurrentApplicationInfo appInfo)
        {
            ServiceSchema           = serviceSchema;
            _serverRequestPublisher = serverRequestPublisher;

            ServiceEndPointDefinition = serviceEndPointDefinition;
            Worker              = worker;
            Activator           = activator;
            Log                 = log;
            CustomEndpoints     = customEndpoints.ToArray();
            Environment         = environment;
            ExceptionSerializer = exceptionSerializer;
            LoadSheddingConfig  = loadSheddingConfig;
            AppInfo             = appInfo;

            if (ServiceEndPointDefinition.HttpsPort != null && ServiceEndPointDefinition.ClientCertificateVerification != ClientCertificateVerificationMode.Disable)
            {
                ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate();
            }

            Listener = new HttpListener {
                IgnoreWriteExceptions = true
            };
            if (ServiceEndPointDefinition.HttpsPort != null)
            {
                Listener.Prefixes.Add($"https://+:{ServiceEndPointDefinition.HttpsPort}/");
            }
            if (ServiceEndPointDefinition.HttpPort != null)
            {
                Listener.Prefixes.Add($"http://+:{ServiceEndPointDefinition.HttpPort}/");
            }
            if (!Listener.Prefixes.Any())
            {
                Log.Warn(_ => _("HttpServiceListener is not listening on any ports, no HTTP or HTTPS ports in ServiceEndPointDefinition"));
            }

            var context = Metric.Context("Service").Context(AppInfo.Name);

            _serializationTime          = context.Timer("Serialization", Unit.Calls);
            _deserializationTime        = context.Timer("Deserialization", Unit.Calls);
            _roundtripTime              = context.Timer("Roundtrip", Unit.Calls);
            _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls);
            _successCounter             = context.Counter("Success", Unit.Calls);
            _failureCounter             = context.Counter("Failed", Unit.Calls);
            _activeRequestsCounter      = context.Timer("ActiveRequests", Unit.Requests);
            _endpointContext            = context.Context("Endpoints");
        }
        public virtual void SetUp()
        {
            TracingContext.SetUpStorage();

            unitTesting = new TestingKernel <ConsoleLog>(mockConfig: MockConfig);
            Metric.ShutdownContext(ServiceProxyProvider.METRICS_CONTEXT_NAME);
            TracingContext.SetRequestID("1");
            ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>();
        }
        public async Task  RequestWithException_ShouldWrapWithUnhandledException()
        {
            _testinghost.Instance.When(a => a.DoSomething()).Throw(x => new ArgumentException("MyEx"));
            var request = await GetRequestFor <IDemoService>(p => p.DoSomething());

            var responseJson      = await(await new HttpClient().SendAsync(request)).Content.ReadAsStringAsync();
            var responseException = JsonExceptionSerializer.Deserialize(responseJson);

            responseException.ShouldBeOfType <UnhandledException>();
        }
        public async Task RequestWithException_ShouldNotWrap(Type exceptionType)
        {
            _testinghost.Instance.When(a => a.DoSomething()).Throw(i => (Exception)Activator.CreateInstance(exceptionType, "MyEx", null, null, null));
            var request = await GetRequestFor <IDemoService>(p => p.DoSomething());

            var responseJson      = await(await new HttpClient().SendAsync(request)).Content.ReadAsStringAsync();
            var responseException = JsonExceptionSerializer.Deserialize(responseJson);

            responseException.ShouldBeOfType(exceptionType);
        }
        public void RequestException_RoundTrip_IsIdentical()
        {
            var expected = new RequestException("message").ThrowAndCatch();
            var json     = JsonExceptionSerializer.Serialize(expected);

            var actual = JsonExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType <RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.StackTrace.ShouldBe(expected.StackTrace);
        }
Example #8
0
        public virtual void SetUp()
        {
            _insecureClient      = _kernel.Get <IDemoService>();
            _exceptionSerializer = _kernel.Get <JsonExceptionSerializer>();

            Metric.ShutdownContext("Service");
            TracingContext.SetUpStorage();
            TracingContext.SetRequestID("1");

            _testinghost = new TestingHost <IDemoService>();
            _stopTask    = _testinghost.RunAsync(new ServiceArguments(ServiceStartupMode.CommandLineNonInteractive));
        }
 public ClientConfiguration(BoltOptions options = null)
 {
     Options             = options ?? new BoltOptions();
     Serializer          = new JsonSerializer();
     ExceptionSerializer = new JsonExceptionSerializer();
     EndpointProvider    = new EndpointProvider(Options);
     SessionHandler      = new ClientSessionHandler(Options);
     ProxyFactory        = new ProxyFactory();
     ErrorProvider       = new ClientErrorProvider(Options.ServerErrorHeader);
     ErrorHandling       = new ErrorHandling();
     HttpMessageHandler  = new HttpClientHandler();
 }
        public void HttpRequestException_RoundTrip_ReturnsSubstitue()
        {
            var ex   = new HttpRequestException("message").ThrowAndCatch();
            var json = JsonExceptionSerializer.Serialize(ex);

            var actual = JsonExceptionSerializer.Deserialize(json);

            var envException = actual.ShouldBeOfType <EnvironmentException>();

            envException.RawMessage().ShouldEndWith(ex.RawMessage());
            envException.UnencryptedTags["originalStackTrace"].ShouldBe(ex.StackTrace);
        }
        public virtual void SetUp()
        {
            var kernel = new TestingKernel<ConsoleLog>();
            _insecureClient = kernel.Get<IDemoService>();
            _exceptionSerializer = kernel.Get<JsonExceptionSerializer>();

            Metric.ShutdownContext("Service");
            TracingContext.SetUpStorage();
            TracingContext.SetRequestID("1");

            _testinghost = new TestingHost<IDemoService>();
            _stopTask = _testinghost.RunAsync();
        }
        public override void OneTimeSetUp()
        {
            base.OneTimeSetUp();
            ExceptionSerializer = _unitTestingKernel.Get <JsonExceptionSerializer>();
            Task t = ChangeConfig <StackTraceEnhancerSettings>(new[]
            {
                new KeyValuePair <string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Pattern",
                                                  @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)"),
                new KeyValuePair <string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Replacement",
                                                  @".$1.$2(async)")
            });

            t.Wait();
        }
Example #13
0
        public HttpServiceListener(IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition,
                                   ICertificateLocator certificateLocator, ILog log,
                                   IEnumerable <ICustomEndpoint> customEndpoints, IEnvironment environment,
                                   JsonExceptionSerializer exceptionSerializer,
                                   ServiceSchema serviceSchema,
                                   Func <LoadShedding> loadSheddingConfig,
                                   IServerRequestPublisher serverRequestPublisher,
                                   CurrentApplicationInfo appInfo
                                   )
        {
            ServiceSchema           = serviceSchema;
            _serverRequestPublisher = serverRequestPublisher;

            ServiceEndPointDefinition = serviceEndPointDefinition;
            Worker              = worker;
            Activator           = activator;
            Log                 = log;
            CustomEndpoints     = customEndpoints.ToArray();
            Environment         = environment;
            ExceptionSerializer = exceptionSerializer;
            LoadSheddingConfig  = loadSheddingConfig;
            AppInfo             = appInfo;

            if (serviceEndPointDefinition.UseSecureChannel)
            {
                ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate();
            }

            var urlPrefixTemplate = ServiceEndPointDefinition.UseSecureChannel ? "https://+:{0}/" : "http://+:{0}/";

            Prefix = string.Format(urlPrefixTemplate, ServiceEndPointDefinition.HttpPort);

            Listener = new HttpListener
            {
                IgnoreWriteExceptions = true,
                Prefixes = { Prefix }
            };

            var context = Metric.Context("Service").Context(AppInfo.Name);

            _serializationTime          = context.Timer("Serialization", Unit.Calls);
            _deserializationTime        = context.Timer("Deserialization", Unit.Calls);
            _roundtripTime              = context.Timer("Roundtrip", Unit.Calls);
            _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls);
            _successCounter             = context.Counter("Success", Unit.Calls);
            _failureCounter             = context.Counter("Failed", Unit.Calls);
            _activeRequestsCounter      = context.Timer("ActiveRequests", Unit.Requests);
            _endpointContext            = context.Context("Endpoints");
        }
        public static HttpResponseMessage GetResponseWithException(Exception ex, HttpStatusCode?statusCode = null, bool withGigyaHostHeader = true)
        {
            var resMessage = new HttpResponseMessage {
                StatusCode = statusCode ?? HttpServiceListener.GetExceptionStatusCode(ex)
            };

            if (withGigyaHostHeader)
            {
                resMessage.Headers.Add(GigyaHttpHeaders.ServerHostname, "host");
            }

            resMessage.Content = new StringContent(JsonExceptionSerializer.Serialize(ex));

            return(resMessage);
        }
        public void InnerHttpRequestException_RoundTrip_IsStripped()
        {
            var webEx  = new WebException("Web exception").ThrowAndCatch();
            var httpEx = new HttpRequestException("HTTP request exception", webEx).ThrowAndCatch();
            var ex     = new RemoteServiceException("Remote service exception", "http://foo/bar", httpEx).ThrowAndCatch();

            string json   = JsonExceptionSerializer.Serialize(ex);
            var    actual = JsonExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType <RemoteServiceException>();
            actual.Message.ShouldBe(ex.Message);
            actual.StackTrace.ShouldBe(ex.StackTrace);
            actual.InnerException.ShouldBeOfType <WebException>();
            actual.InnerException.Message.ShouldBe(webEx.Message);
            actual.InnerException.StackTrace.ShouldBe(webEx.StackTrace);
        }
Example #16
0
        public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher,
                                    ICertificateLocator certificateLocator,
                                    ILog log,
                                    Func <string, ReachabilityChecker, IServiceDiscovery> serviceDiscoveryFactory,
                                    Func <DiscoveryConfig> getConfig,
                                    JsonExceptionSerializer exceptionSerializer)
        {
            EventPublisher     = eventPublisher;
            CertificateLocator = certificateLocator;

            Log = log;

            ServiceName         = serviceName;
            GetDiscoveryConfig  = getConfig;
            ExceptionSerializer = exceptionSerializer;

            ServiceDiscovery = serviceDiscoveryFactory(serviceName, IsReachable);
        }
        public void SetUp()
        {
            var unitTesting = new TestingKernel <ConsoleLog>(k =>
                                                             k.Rebind <Func <StackTraceEnhancerSettings> >().ToConstant <Func <StackTraceEnhancerSettings> >(() => new StackTraceEnhancerSettings
            {
                RegexReplacements = new Dictionary <string, RegexReplace>
                {
                    ["TidyAsyncLocalFunctionNames"] = new RegexReplace
                    {
                        Pattern     = @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)",
                        Replacement = @".$1.$2(async)"
                    }
                }
            })
                                                             );

            ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>();
        }
        public void ExceptionTypeNotAvailable_RoundTrip_FallsBackToAvailableType()
        {
            var expected = new MyException(30000, "message")
            {
                MyNumber = 42
            }.ThrowAndCatch();
            var json = JsonExceptionSerializer.Serialize(expected);

            json = json.Replace("MyException", "MyNonexistentException");
            var actual = (RequestException)JsonExceptionSerializer.Deserialize(json);

            actual.ShouldBeOfType <RequestException>();
            actual.Message.ShouldBe(expected.Message);
            actual.ErrorCode.ShouldBe(30000);
            actual.ExtendedProperties.Count.ShouldBe(1);
            actual.ExtendedProperties.Single().ShouldBe(new KeyValuePair <string, object>("MyNumber", 42L));
            actual.StackTrace.ShouldBe(expected.StackTrace);
        }
        public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher,
                                    ILog log,
                                    Func <string, ReachabilityCheck, IMultiEnvironmentServiceDiscovery> serviceDiscoveryFactory,
                                    Func <DiscoveryConfig> getConfig,
                                    JsonExceptionSerializer exceptionSerializer,
                                    CurrentApplicationInfo appInfo,
                                    Func <HttpClientConfiguration, HttpMessageHandler> messageHandlerFactory,
                                    IMicrodotTypePolicySerializationBinder serializationBinder)
        {
            JsonSettings.SerializationBinder = serializationBinder;

            EventPublisher = eventPublisher;

            Log = log;

            ServiceName         = serviceName;
            GetDiscoveryConfig  = getConfig;
            ExceptionSerializer = exceptionSerializer;
            AppInfo             = appInfo;

            var metricsContext = Metric.Context(METRICS_CONTEXT_NAME).Context(ServiceName);

            _serializationTime   = metricsContext.Timer("Serialization", Unit.Calls);
            _deserializationTime = metricsContext.Timer("Deserialization", Unit.Calls);
            _roundtripTime       = metricsContext.Timer("Roundtrip", Unit.Calls);

            _successCounter              = metricsContext.Counter("Success", Unit.Calls);
            _failureCounter              = metricsContext.Counter("Failed", Unit.Calls);
            _hostFailureCounter          = metricsContext.Counter("HostFailure", Unit.Calls);
            _applicationExceptionCounter = metricsContext.Counter("ApplicationException", Unit.Calls);

            _httpMessageHandlerFactory = messageHandlerFactory;

            ServiceDiscovery = serviceDiscoveryFactory(serviceName, ValidateReachability);

            var globalConfig  = GetDiscoveryConfig();
            var serviceConfig = GetConfig();

            _httpsTestInterval = TimeSpan.FromMinutes(serviceConfig.TryHttpsIntervalInMinutes ?? globalConfig.TryHttpsIntervalInMinutes);

            _connectionContext = Metric.Context("Connections");
        }
Example #20
0
        public void SetUp()
        {
            var unitTesting = new TestingKernel <ConsoleLog>(k =>
                                                             k.Rebind <Func <StackTraceEnhancerSettings> >().ToConstant <Func <StackTraceEnhancerSettings> >(() => new StackTraceEnhancerSettings
            {
                RegexReplacements =
                {
                    ["TidyAsyncMethodNames"] = new RegexReplace        {
                        Pattern = @"\.<(\w+)>d__\d+(?:`\d)?.MoveNext\(\)", Replacement = @".$1(async)"
                    },
                    ["TidyAsyncLocalFunctionNames"] = new RegexReplace {
                        Pattern = @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\d>d.MoveNext\(\)", Replacement = @".$1.$2(async)"
                    },
                    ["RemoveBuildServerPath"] = new RegexReplace       {
                        Pattern = @"C:\\BuildAgent\\work\\\w+\\", Replacement = @"\"
                    }
                }
            })
                                                             );

            ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>();
        }
        private async Task <object> InvokeCore(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            request.Overrides   = TracingContext.TryGetOverrides();
            request.TracingData = new TracingData
            {
                HostName     = CurrentApplicationInfo.HostName?.ToUpperInvariant(),
                ServiceName  = CurrentApplicationInfo.Name,
                RequestID    = TracingContext.TryGetRequestID(),
                SpanID       = Guid.NewGuid().ToString("N"), //Each call is new span
                ParentSpanID = TracingContext.TryGetSpanID()
            };
            PrepareRequest?.Invoke(request);
            var requestContent = _serializationTime.Time(() => JsonConvert.SerializeObject(request, jsonSettings));

            var serviceEvent = EventPublisher.CreateEvent();

            serviceEvent.TargetService = ServiceName;
            serviceEvent.TargetMethod  = request.Target.MethodName;
            serviceEvent.RequestId     = request.TracingData?.RequestID;
            serviceEvent.SpanId        = request.TracingData?.SpanID;
            serviceEvent.ParentSpanId  = request.TracingData?.ParentSpanID;

            var config = GetConfig();

            while (true)
            {
                string responseContent;
                HttpResponseMessage response;
                IEndPointHandle     endPoint = await ServiceDiscovery.GetNextHost(serviceEvent.RequestId).ConfigureAwait(false);

                // The URL is only for a nice experience in Fiddler, it's never parsed/used for anything.
                var uri = string.Format(BuildUri(endPoint, config) + ServiceName);
                if (request.Target.MethodName != null)
                {
                    uri += $".{request.Target.MethodName}";
                }
                if (request.Target.Endpoint != null)
                {
                    uri += $"/{request.Target.Endpoint}";
                }

                try
                {
                    Log.Debug(_ => _("ServiceProxy: Calling remote service. See tags for details.",
                                     unencryptedTags: new
                    {
                        remoteEndpoint    = endPoint.HostName,
                        remotePort        = endPoint.Port ?? DefaultPort,
                        remoteServiceName = ServiceName,
                        remoteMethodName  = request.Target.MethodName
                    }));

                    serviceEvent.TargetHostName = endPoint.HostName;
                    var httpContent = new StringContent(requestContent, Encoding.UTF8, "application/json");
                    httpContent.Headers.Add(GigyaHttpHeaders.Version, HttpServiceRequest.Version);

                    serviceEvent.RequestStartTimestamp = Stopwatch.GetTimestamp();
                    try
                    {
                        response = await GetHttpClient(config).PostAsync(uri, httpContent).ConfigureAwait(false);

                        responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                    finally
                    {
                        serviceEvent.ResponseEndTimestamp = Stopwatch.GetTimestamp();
                    }
                    IEnumerable <string> values;
                    if (response.Headers.TryGetValues(GigyaHttpHeaders.ExecutionTime, out values))
                    {
                        var      time = values.FirstOrDefault();
                        TimeSpan executionTime;
                        if (TimeSpan.TryParse(time, out executionTime))
                        {
                            serviceEvent.ServerTimeMs = executionTime.TotalMilliseconds;
                        }
                    }
                }
                catch (HttpRequestException ex)
                {
                    Log.Error("The remote service failed to return a valid HTTP response. Continuing to next " +
                              "host. See tags for URL and exception for details.",
                              exception: ex,
                              unencryptedTags: new { uri });

                    endPoint.ReportFailure(ex);
                    _hostFailureCounter.Increment("RequestFailure");
                    serviceEvent.Exception = ex;
                    EventPublisher.TryPublish(serviceEvent); // fire and forget!
                    continue;
                }
                catch (TaskCanceledException ex)
                {
                    _failureCounter.Increment("RequestTimeout");

                    Exception rex = new RemoteServiceException("The request to the remote service exceeded the " +
                                                               "allotted timeout. See the 'RequestUri' property on this exception for the URL that was " +
                                                               "called and the tag 'requestTimeout' for the configured timeout.",
                                                               uri,
                                                               ex,
                                                               unencrypted: new Tags
                    {
                        { "requestTimeout", LastHttpClient?.Timeout.ToString() },
                        { "requestUri", uri }
                    });

                    serviceEvent.Exception = rex;

                    EventPublisher.TryPublish(serviceEvent); // fire and forget!
                    throw rex;
                }

                if (response.Headers.Contains(GigyaHttpHeaders.ServerHostname) || response.Headers.Contains(GigyaHttpHeaders.Version))
                {
                    try
                    {
                        endPoint.ReportSuccess();

                        if (response.IsSuccessStatusCode)
                        {
                            var returnObj = _deserializationTime.Time(() => JsonConvert.DeserializeObject(responseContent, resultReturnType, jsonSettings));

                            serviceEvent.ErrCode = 0;
                            EventPublisher.TryPublish(serviceEvent); // fire and forget!
                            _successCounter.Increment();

                            return(returnObj);
                        }
                        else
                        {
                            Exception remoteException;

                            try
                            {
                                remoteException = _deserializationTime.Time(() => JsonExceptionSerializer.Deserialize(responseContent));
                            }
                            catch (Exception ex)
                            {
                                _applicationExceptionCounter.Increment("ExceptionDeserializationFailure");

                                throw new RemoteServiceException("The remote service returned a failure response " +
                                                                 "that failed to deserialize.  See the 'RequestUri' property on this exception " +
                                                                 "for the URL that was called, the inner exception for the exact error and the " +
                                                                 "'responseContent' encrypted tag for the original response content.",
                                                                 uri,
                                                                 ex,
                                                                 unencrypted: new Tags {
                                    { "requestUri", uri }
                                },
                                                                 encrypted: new Tags {
                                    { "responseContent", responseContent }
                                });
                            }

                            _applicationExceptionCounter.Increment();

                            serviceEvent.Exception = remoteException;
                            EventPublisher.TryPublish(serviceEvent); // fire and forget!

                            if (remoteException is RequestException || remoteException is EnvironmentException)
                            {
                                ExceptionDispatchInfo.Capture(remoteException).Throw();
                            }

                            if (remoteException is UnhandledException)
                            {
                                remoteException = remoteException.InnerException;
                            }

                            throw new RemoteServiceException("The remote service returned a failure response. See " +
                                                             "the 'RequestUri' property on this exception for the URL that was called, and the " +
                                                             "inner exception for details.",
                                                             uri,
                                                             remoteException,
                                                             unencrypted: new Tags {
                                { "requestUri", uri }
                            });
                        }
                    }
                    catch (JsonException ex)
                    {
                        _failureCounter.Increment("Serialization");

                        Log.Error(_ => _("The remote service returned a response with JSON that failed " +
                                         "deserialization. See the 'uri' tag for the URL that was called, the exception for the " +
                                         "exact error and the 'responseContent' encrypted tag for the original response content.",
                                         exception: ex,
                                         unencryptedTags: new { uri },
                                         encryptedTags: new { responseContent }));

                        serviceEvent.Exception = ex;
                        EventPublisher.TryPublish(serviceEvent); // fire and forget!
                        throw new RemoteServiceException("The remote service returned a response with JSON that " +
                                                         "failed deserialization. See the 'RequestUri' property on this exception for the URL " +
                                                         "that was called, the inner exception for the exact error and the 'responseContent' " +
                                                         "encrypted tag for the original response content.",
                                                         uri,
                                                         ex,
                                                         new Tags {
                            { "responseContent", responseContent }
                        },
                                                         new Tags {
                            { "requestUri", uri }
                        });
                    }
                }
                else
                {
                    var exception = response.StatusCode == HttpStatusCode.ServiceUnavailable ?
                                    new Exception($"The remote service is unavailable (503) and is not recognized as a Gigya host at uri: {uri}"):
                                    new Exception($"The remote service returned a response but is not recognized as a Gigya host at uri: {uri}");

                    endPoint.ReportFailure(exception);
                    _hostFailureCounter.Increment("NotGigyaHost");

                    if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
                    {
                        Log.Error(_ => _("The remote service is unavailable (503) and is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri }));
                    }
                    else
                    {
                        Log.Error(_ => _("The remote service returned a response but is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri, statusCode = response.StatusCode }, encryptedTags: new { responseContent }));
                    }

                    serviceEvent.ErrCode = 500001;           //(int)GSErrors.General_Server_Error;
                    EventPublisher.TryPublish(serviceEvent); // fire and forget!
                }
            }
        }
Example #22
0
 public JsonExceptionWrapperTest()
 {
     Subject = new JsonExceptionSerializer();
 }
        private async Task HandleRequest(HttpListenerContext context)
        {
            RequestTimings.ClearCurrentTimings();
            using (context.Response)
            {
                var sw = Stopwatch.StartNew();

                // Special endpoints should not be logged/measured/traced like regular endpoints
                try
                {
                    foreach (var customEndpoint in CustomEndpoints)
                    {
                        if (await customEndpoint.TryHandle(context, (data, status, type) => TryWriteResponse(context, data, status, type)))
                        {
                            if (RequestTimings.Current.Request.ElapsedMS != null)
                            {
                                _metaEndpointsRoundtripTime.Record((long)RequestTimings.Current.Request.ElapsedMS, TimeUnit.Milliseconds);
                            }
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    var ex = GetRelevantException(e);
                    await TryWriteResponse(context, JsonExceptionSerializer.Serialize(ex), GetExceptionStatusCode(ex));

                    return;
                }

                // Regular endpoint handling
                using (_activeRequestsCounter.NewContext("Request"))
                {
                    TracingContext.SetUpStorage();
                    Exception ex;
                    Exception actualException = null;
                    string    methodName      = null;
                    // Initialize with empty object for protocol backwards-compatibility.
                    var requestData = new HttpServiceRequest {
                        TracingData = new TracingData()
                    };

                    ServiceMethod serviceMethod = null;
                    try
                    {
                        try
                        {
                            ValidateRequest(context);
                            await CheckSecureConnection(context);

                            requestData = await ParseRequest(context);

                            TracingContext.SetOverrides(requestData.Overrides);

                            serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                            methodName    = serviceMethod.ServiceInterfaceMethod.Name;
                        }
                        catch (Exception e)
                        {
                            actualException = e;
                            if (e is RequestException)
                            {
                                throw;
                            }

                            throw new RequestException("Invalid request", e);
                        }

                        var responseJson = await GetResponse(context, serviceMethod, requestData);
                        await TryWriteResponse(context, responseJson);

                        _successCounter.Increment();
                    }
                    catch (Exception e)
                    {
                        actualException = actualException ?? e;
                        _failureCounter.Increment();
                        ex = GetRelevantException(e);

                        string json = _serializationTime.Time(() => JsonExceptionSerializer.Serialize(ex));
                        await TryWriteResponse(context, json, GetExceptionStatusCode(ex));
                    }
                    finally
                    {
                        sw.Stop();
                        _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        if (methodName != null)
                        {
                            _endpointContext.Timer(methodName, Unit.Requests).Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds);
                        }
                        PublishEvent(requestData, actualException, serviceMethod, sw.Elapsed.TotalMilliseconds);
                    }
                }
            }
        }
        public HttpServiceListener(
            IActivator activator,
            IWorker worker,
            IServiceEndPointDefinition serviceEndPointDefinition,
            ICertificateLocator certificateLocator,
            ILog log,
            IEnumerable <ICustomEndpoint> customEndpoints,
            IEnvironment environment,
            JsonExceptionSerializer exceptionSerializer,
            ServiceSchema serviceSchema,
            Func <LoadShedding> loadSheddingConfig,
            IServerRequestPublisher serverRequestPublisher,
            CurrentApplicationInfo appInfo,
            Func <MicrodotHostingConfig> microdotHostingConfigFactory,
            IMicrodotTypePolicySerializationBinder serializationBinder)
        {
            ServiceSchema           = serviceSchema;
            _serverRequestPublisher = serverRequestPublisher;

            ServiceEndPointDefinition = serviceEndPointDefinition;
            Worker              = worker;
            Activator           = activator;
            Log                 = log;
            CustomEndpoints     = customEndpoints.ToArray();
            Environment         = environment;
            ExceptionSerializer = exceptionSerializer;
            LoadSheddingConfig  = loadSheddingConfig;
            AppInfo             = appInfo;

            JsonSettings.SerializationBinder = serializationBinder;

            if (ServiceEndPointDefinition.HttpsPort != null && ServiceEndPointDefinition.ClientCertificateVerification != ClientCertificateVerificationMode.Disable)
            {
                var serviceCertificate = certificateLocator.GetCertificate("Service");
                Log.Info(_ => _($"Service certificate loaded: {serviceCertificate.FriendlyName}",
                                unencryptedTags: new
                {
                    Thumbprint = serviceCertificate.Thumbprint.Substring(serviceCertificate.Thumbprint.Length - 5),
                }));
                ServerRootCertHash = serviceCertificate.GetHashOfRootCertificate();
            }

            Listener = new HttpListener {
                IgnoreWriteExceptions = true
            };

            _uriPrefixes = new List <string>();

            if (ServiceEndPointDefinition.HttpsPort != null)
            {
                _uriPrefixes.Add($"https://+:{ServiceEndPointDefinition.HttpsPort}/");
            }
            if (ServiceEndPointDefinition.HttpPort != null)
            {
                _uriPrefixes.Add($"http://+:{ServiceEndPointDefinition.HttpPort}/");
            }
            if (!_uriPrefixes.Any())
            {
                Log.Warn(_ => _("HttpServiceListener is not listening on any ports, no HTTP or HTTPS ports in ServiceEndPointDefinition"));
            }
            else
            {
                foreach (string prefix in _uriPrefixes)
                {
                    Listener.Prefixes.Add(prefix);
                }
            }


            var context = Metric.Context("Service").Context(AppInfo.Name);

            _serializationTime          = context.Timer("Serialization", Unit.Calls);
            _deserializationTime        = context.Timer("Deserialization", Unit.Calls);
            _roundtripTime              = context.Timer("Roundtrip", Unit.Calls);
            _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls);
            _successCounter             = context.Counter("Success", Unit.Calls);
            _failureCounter             = context.Counter("Failed", Unit.Calls);
            _activeRequestsCounter      = context.Timer("ActiveRequests", Unit.Requests);
            _endpointContext            = context.Context("Endpoints");
        }