示例#1
0
        private async Task <object> InvokeCore(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            request.TracingData = new TracingData
            {
                HostName         = CurrentApplicationInfo.HostName?.ToUpperInvariant(),
                ServiceName      = AppInfo.Name,
                RequestID        = TracingContext.TryGetRequestID(),
                SpanID           = Guid.NewGuid().ToString("N"), //Each call is new span
                ParentSpanID     = TracingContext.TryGetParentSpanID(),
                SpanStartTime    = DateTimeOffset.UtcNow,
                AbandonRequestBy = TracingContext.AbandonRequestBy
            };
            PrepareRequest?.Invoke(request);

            while (true)
            {
                var config          = GetConfig();
                var clientCallEvent = EventPublisher.CreateEvent();
                clientCallEvent.TargetService = ServiceName;
                clientCallEvent.RequestId     = request.TracingData?.RequestID;
                clientCallEvent.TargetMethod  = request.Target.MethodName;
                clientCallEvent.SpanId        = request.TracingData?.SpanID;
                clientCallEvent.ParentSpanId  = request.TracingData?.ParentSpanID;

                string responseContent;
                HttpResponseMessage response;
                var nodeAndLoadBalancer = await ServiceDiscovery.GetNode().ConfigureAwait(false); // can throw

                int?effectivePort = GetEffectivePort(nodeAndLoadBalancer.Node, config);
                if (effectivePort == null)
                {
                    throw new ConfigurationException("Cannot access service. Service Port not configured. See tags to find missing configuration", unencrypted: new Tags {
                        { "ServiceName", ServiceName },
                        { "Required configuration key", $"Discovery.{ServiceName}.DefaultPort" }
                    });
                }

                // The URL is only for a nice experience in Fiddler, it's never parsed/used for anything.
                var uri = BuildUri(nodeAndLoadBalancer.Node.Hostname, effectivePort.Value, 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    = nodeAndLoadBalancer.Node.Hostname,
                        remotePort        = effectivePort,
                        remoteServiceName = ServiceName,
                        remoteMethodName  = request.Target.MethodName
                    }));

                    clientCallEvent.TargetHostName    = nodeAndLoadBalancer.Node.Hostname;
                    clientCallEvent.TargetPort        = effectivePort.Value;
                    clientCallEvent.TargetEnvironment = nodeAndLoadBalancer.TargetEnvironment;

                    request.Overrides = TracingContext.TryGetOverrides()?.ShallowCloneWithDifferentPreferredEnvironment(nodeAndLoadBalancer.PreferredEnvironment)
                                        ?? new RequestOverrides {
                        PreferredEnvironment = nodeAndLoadBalancer.PreferredEnvironment
                    };
                    string requestContent = _serializationTime.Time(() => JsonConvert.SerializeObject(request, jsonSettings));

                    var httpContent = new StringContent(requestContent, Encoding.UTF8, "application/json");
                    httpContent.Headers.Add(GigyaHttpHeaders.ProtocolVersion, HttpServiceRequest.ProtocolVersion);

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

                        responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                    finally
                    {
                        clientCallEvent.ResponseEndTimestamp = Stopwatch.GetTimestamp();
                    }
                    if (response.Headers.TryGetValues(GigyaHttpHeaders.ExecutionTime, out IEnumerable <string> values))
                    {
                        var time = values.FirstOrDefault();
                        if (TimeSpan.TryParse(time, out TimeSpan executionTime))
                        {
                            clientCallEvent.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 });
                    _hostFailureCounter.Increment("RequestFailure");
                    clientCallEvent.Exception = ex;
                    EventPublisher.TryPublish(clientCallEvent); // fire and forget!

                    if (nodeAndLoadBalancer.LoadBalancer != null)
                    {
                        nodeAndLoadBalancer.LoadBalancer.ReportUnreachable(nodeAndLoadBalancer.Node, ex);
                        continue;
                    }

                    throw;
                }
                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 }
                    });

                    clientCallEvent.Exception = rex;

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

                if (response.Headers.Contains(GigyaHttpHeaders.ServerHostname) || response.Headers.Contains(GigyaHttpHeaders.ProtocolVersion))
                {
                    try
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            var returnObj = _deserializationTime.Time(() => JsonConvert.DeserializeObject(responseContent, resultReturnType, jsonSettings));

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

                            return(returnObj);
                        }
                        else
                        {
                            Exception remoteException;

                            try
                            {
                                remoteException = _deserializationTime.Time(() => ExceptionSerializer.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();

                            clientCallEvent.Exception = remoteException;
                            EventPublisher.TryPublish(clientCallEvent); // 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 });

                        clientCallEvent.Exception = ex;
                        EventPublisher.TryPublish(clientCallEvent); // 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}");
                    if (nodeAndLoadBalancer.LoadBalancer == null)
                    {
                        throw exception;
                    }

                    nodeAndLoadBalancer.LoadBalancer.ReportUnreachable(nodeAndLoadBalancer.Node, 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 });
                    }

                    clientCallEvent.ErrCode = 500001;           //(int)GSErrors.General_Server_Error;
                    EventPublisher.TryPublish(clientCallEvent); // fire and forget!
                }
            }
        }
示例#2
0
 public virtual Task <object> Invoke(HttpServiceRequest request, Type resultReturnType)
 {
     return(Invoke(request, resultReturnType, JsonSettings));
 }
示例#3
0
 public virtual async Task <object> Invoke(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings)
 {
     using (_roundtripTime.NewContext())
         return(await InvokeCore(request, resultReturnType, jsonSettings).ConfigureAwait(false));
 }
示例#4
0
        private async Task <string> GetResponse(HttpListenerContext context, ServiceMethod serviceMethod, HttpServiceRequest requestData)
        {
            var taskType   = serviceMethod.ServiceInterfaceMethod.ReturnType;
            var resultType = taskType.IsGenericType ? taskType.GetGenericArguments().First() : null;
            var arguments  = requestData.Target.IsWeaklyTyped ? GetParametersByName(serviceMethod, requestData.Arguments) : requestData.Arguments.Values.Cast <object>().ToArray();
            var settings   = requestData.Target.IsWeaklyTyped ? JsonSettingsWeak : JsonSettings;

            var invocationResult = await Activator.Invoke(serviceMethod, arguments);

            string response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, resultType, settings));

            context.Response.Headers.Add(GigyaHttpHeaders.ExecutionTime, invocationResult.ExecutionTime.ToString());

            return(response);
        }
示例#5
0
 private WebApiResponse SendRequest(HttpServiceRequest request)
 {
     throw new NotImplementedException();
 }
示例#6
0
        private async Task HandleRequest(HttpListenerContext context, long ticks, long timeFromLastReq)
        {
            var sw = _stopwatchPool.Get();

            try
            {
                var deltaDelayTicks = DateTime.UtcNow.Ticks - ticks;
                sw.Restart();
                RequestTimings.ClearCurrentTimings();
                using (context.Response)
                {
                    // Special endpoints should not be logged/measured/traced like regular endpoints
                    // Access is allowed without HTTPS verifications since they don't expose anything sensitive (e.g. config values are encrypted)
                    if (await TryHandleSpecialEndpoints(context))
                    {
                        return;
                    }

                    // Regular endpoint handling
                    using (_activeRequestsCounter.NewContext("Request"))
                    {
                        RequestTimings.GetOrCreate(); // initialize request timing context

                        string methodName = null;
                        // Initialize with empty object for protocol backwards-compatibility.

                        var requestData = new HttpServiceRequest {
                            TracingData = new TracingData()
                        };
                        object[]         argumentsWithDefaults = null;
                        ServiceMethod    serviceMethod         = null;
                        ServiceCallEvent callEvent             = _serverRequestPublisher.GetNewCallEvent();
                        try
                        {
                            try
                            {
                                await CheckSecureConnection(context);

                                ValidateRequest(context);

                                requestData = await ParseRequest(context);


                                //-----------------------------------------------------------------------------------------
                                // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes
                                //-----------------------------------------------------------------------------------------
                                TracingContext.SetRequestID(requestData.TracingData.RequestID);
                                TracingContext.SpanStartTime    = requestData.TracingData.SpanStartTime;
                                TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy;
                                TracingContext.SetParentSpan(
                                    requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N"));
                                TracingContext.SetOverrides(requestData.Overrides);
                                if (requestData.TracingData.Tags != null)
                                {
                                    TracingContext.Tags = new ContextTags(requestData.TracingData.Tags);
                                }
                                TracingContext.AdditionalProperties = requestData.TracingData.AdditionalProperties;

                                callEvent.ServiceMethodSchema = context.Request.IsSecureConnection ? "HTTPS" : "HTTP";
                                SetCallEventRequestData(callEvent, requestData);

                                serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                                callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name;
                                methodName = serviceMethod.ServiceInterfaceMethod.Name;
                                var arguments = requestData.Target.IsWeaklyTyped
                                    ? GetParametersByName(serviceMethod, requestData.Arguments)
                                    : requestData.Arguments.Values.Cast <object>().ToArray();
                                argumentsWithDefaults =
                                    GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments);

                                if (_extendedDelayTimeLogging)
                                {
                                    callEvent.RecvDateTicks        = ticks;
                                    callEvent.ReqStartupDeltaTicks = deltaDelayTicks;
                                    callEvent.TimeFromLastReq      = timeFromLastReq;
                                    var outstandingRecvReqs = Interlocked.Read(ref _outstandingRecvRequests);
                                    callEvent.OutstandingRecvRequests = outstandingRecvReqs;
                                    if (deltaDelayTicks > 10_000_000)
                                    {
                                        callEvent.CollectionCountGen0 = GC.CollectionCount(0);
                                        callEvent.CollectionCountGen1 = GC.CollectionCount(1);
                                        callEvent.CollectionCountGen2 = GC.CollectionCount(2);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                callEvent.Exception = e;
                                if (e is RequestException)
                                {
                                    throw;
                                }

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

                            RejectRequestIfLateOrOverloaded();

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

                            if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent))
                            {
                                callEvent.ErrCode = 0;
                                _successCounter.Increment();
                            }
                            else
                            {
                                _failureCounter.Increment();
                            }
                        }
                        catch (Exception e)
                        {
                            callEvent.Exception = callEvent.Exception ?? e;
                            _failureCounter.Increment();
                            Exception ex   = GetRelevantException(e);
                            string    json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                            await TryWriteResponse(context, json, GetExceptionStatusCode(ex),
                                                   serviceCallEvent : callEvent);
                        }
                        finally
                        {
                            sw.Stop();
                            callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds;

                            _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);
                            }

                            _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod);
                        }
                    }
                }
            }
            finally
            {
                _stopwatchPool.Return(sw);
                Interlocked.Decrement(ref _outstandingRecvRequests);
            }
        }
示例#7
0
        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();
                    RequestTimings.GetOrCreate(); // initialize request timing context

                    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);
                    }
                }
            }
        }
示例#8
0
        public async Task HttpsStoppedListening_FallbackToHttp()
        {
            var host            = "host1";
            var httpsPortOffset = 5;
            var port            = DisposablePort.GetPort().Port;
            var dict            = new Dictionary <string, string>
            {
                { "Discovery.Services.DemoService.Source", "Config" },
                { "Discovery.Services.DemoService.Hosts", host },
                { "Discovery.Services.DemoService.DefaultPort", port.ToString() }
            };

            int  httpsTestCount    = 0;
            bool httpsMethodCalled = false;

            Func <bool, string, HttpMessageHandler> messageHandlerFactory = (_, __) =>
            {
                var messageHandler = new MockHttpMessageHandler();
                messageHandler
                .When("https://*")
                .Respond(req =>
                {
                    if (httpsMethodCalled)
                    {
                        throw new HttpRequestException("", new WebException("", WebExceptionStatus.ProtocolError));
                    }
                    if (req.RequestUri.AbsoluteUri == $"https://{host}:{port + httpsPortOffset}/")
                    {
                        httpsTestCount++;
                        return(HttpResponseFactory.GetResponse(content: "'some HTTPS response'"));
                    }

                    if (req.RequestUri.AbsoluteUri == $"https://{host}:{port + httpsPortOffset}/DemoService.testMethod")
                    {
                        httpsMethodCalled = true;
                        return(HttpResponseFactory.GetResponse(content: "'some HTTPS response'"));
                    }

                    throw new HttpRequestException("Invalid uri");
                });
                messageHandler
                .When("http://*")
                .Respond(req =>
                {
                    if (req.RequestUri.AbsoluteUri == $"http://{host}:{port}/DemoService.testMethod")
                    {
                        return(HttpResponseFactory.GetResponse(content: "'some HTTP response'"));
                    }
                    if (req.RequestUri.AbsoluteUri == $"http://{host}:{port}/")
                    {
                        return(HttpResponseFactory.GetResponse(content: "'{X-Gigya-ServerHostname: someValue}'"));
                    }
                    throw new HttpRequestException("Invalid uri");
                });

                return(messageHandler);
            };

            using (var kernel =
                       new TestingKernel <ConsoleLog>(
                           k =>
            {
                k.Rebind <IDiscovery>().To <ServiceDiscovery.Rewrite.Discovery>().InSingletonScope();
                k.Rebind <Func <bool, string, HttpMessageHandler> >().ToMethod(c => messageHandlerFactory);
            }, dict)
                   )
            {
                var providerFactory = kernel.Get <Func <string, ServiceProxyProvider> >();
                var serviceProxy    = providerFactory("DemoService");
                serviceProxy.DefaultPort = port;
                TracingContext.SetRequestID("1");

                var request = new HttpServiceRequest("testMethod", null, new Dictionary <string, object>());

                var server = await serviceProxy.Invoke(request, typeof(string));

                server.ShouldBe("some HTTP response");

                Assert.That(() => httpsTestCount, Is.EqualTo(1).After(10).Seconds.PollEvery(1).Seconds);

                server = await serviceProxy.Invoke(request, typeof(string));

                server.ShouldBe("some HTTPS response");

                server = await serviceProxy.Invoke(request, typeof(string));

                server.ShouldBe("some HTTP response");
            }
        }
        protected override void ExecuteCore()
        {
            var group = new ProgressGroup {
                Status = Strings.UpdatingStatus
            };

            ProgressManager.Current.Register(group);

            try
            {
                foreach (var config in status.TargetChannels)
                {
                    var channel = ChannelsManager.GetChannelObject(config.ChannelId);

                    try
                    {
                        group.SourceChannelId = config.ChannelId;

                        ChannelContext.Current.ClientContext = new ChannelClientContext(ClientState.Current.Context, config);

                        Logger.Debug("Updating status. Channel = {0}", LogSource.BackgroundTask, config.DisplayName);

                        if (config.IsConnected)
                        {
                            var data = String.Format("wrap_access_token={0}&channels={1}&inreplyto={2}&body={3}",
                                                     CloudApi.AccessToken, config.ChannelKey, status.InReplyTo, HttpUtility.UrlEncode(status.Status));

                            HttpServiceRequest.Post(String.Concat(CloudApi.ApiBaseUrl, "send/statusupdate"), data, true);
                        }
                        else
                        {
                            channel.StatusUpdatesChannel.UpdateMyStatus(status.DuckCopy <ChannelStatusUpdate>());
                        }
                    }
                    catch (Exception ex)
                    {
                        ClientState.Current.ShowMessage(
                            new AppMessage(
                                String.Concat(
                                    String.Format(Strings.ErrorOccuredDuringStatusUpdate, channel.Configuration.DisplayName),
                                    String.Format(Strings.ServerSaid, ex.Message)))
                        {
                            SourceChannelId = config.ChannelId
                        }, MessageType.Error);

                        throw;
                    }
                }

                Thread.CurrentThread.ExecuteOnUIThread(() =>
                                                       ClientState.Current.ShowMessage(
                                                           new AppMessage(Strings.StatusUpdatedSuccessfully)
                {
                    EntityId   = status.StatusId,
                    EntityType = EntityType.UserStatus
                }, MessageType.Success));
            }
            finally
            {
                group.IsCompleted = true;
            }
        }
示例#10
0
        public async Task HttpsDisabled_NoCertificate_CallSucceeds()
        {
            var host            = "host1";
            var httpsPortOffset = 5;
            var port            = DisposablePort.GetPort().Port;
            var dict            = new Dictionary <string, string>
            {
                { "Discovery.Services.DemoService.Source", "Config" },
                { "Discovery.Services.DemoService.Hosts", host },
                { "Discovery.Services.DemoService.DefaultPort", port.ToString() },
                { "Discovery.Services.DemoService.UseHttpsOverride", "false" }
            };

            int  httpsTestCount    = 0;
            bool httpsMethodCalled = false;

            Func <HttpClientConfiguration, HttpMessageHandler> messageHandlerFactory = _ =>
            {
                var messageHandler = new MockHttpMessageHandler();
                messageHandler
                .When("https://*")
                .Respond(req =>
                         HttpResponseFactory.GetResponseWithException(ExceptionSerializer, new SocketException()));

                messageHandler
                .When("http://*")
                .Respond(req => HttpResponseFactory.GetResponse(content: "'some HTTP response'"));

                return(messageHandler);
            };

            using (var kernel =
                       new TestingKernel <ConsoleLog>(
                           k =>
            {
                k.Rebind <IDiscovery>().To <ServiceDiscovery.Rewrite.Discovery>().InSingletonScope();
                k.Rebind <Func <HttpClientConfiguration, HttpMessageHandler> >().ToMethod(c => messageHandlerFactory);

                var certificateLocator = Substitute.For <ICertificateLocator>();
                certificateLocator
                .When(cl => cl.GetCertificate(Arg.Any <string>()))
                .Do(x => throw new Exception());
                k.Rebind <ICertificateLocator>().ToConstant(certificateLocator);

                var httpsAuthenticator = Substitute.For <IHttpsAuthenticator>();
                httpsAuthenticator
                .When(a => a.AddHttpMessageHandlerAuthentication(Arg.Any <HttpClientHandler>(), Arg.Any <HttpClientConfiguration>()))
                .Do(x => throw new Exception());
                k.Rebind <IHttpsAuthenticator>().ToConstant(httpsAuthenticator);
            }, dict)
                   )
            {
                var providerFactory = kernel.Get <Func <string, ServiceProxyProvider> >();
                var serviceProxy    = providerFactory("DemoService");
                serviceProxy.DefaultPort = port;
                TracingContext.SetRequestID("1");

                var request = new HttpServiceRequest("testMethod", null, new Dictionary <string, object>());

                await serviceProxy.Invoke(request, typeof(string));
            }
        }
示例#11
0
        public async Task RequestContextOverrideShouldFailOnFirstAttempt()
        {
            var port = DisposablePort.GetPort().Port;
            var dict = new Dictionary <string, string>
            {
                { "Discovery.Services.DemoService.Source", "Config" },
                { "Discovery.Services.DemoService.Hosts", "notImpotent" },
                { "Discovery.Services.DemoService.DefaultPort", port.ToString() }
            };

            int counter = 0;
            Func <bool, string, HttpMessageHandler> messageHandlerFactory = (_, __) =>
            {
                var messageHandler = new MockHttpMessageHandler();
                messageHandler
                .When("*")
                .Respond(req =>
                {
                    if (req.Method == HttpMethod.Get && req.RequestUri.Scheme == "https")
                    {
                        throw new HttpRequestException();
                    }

                    counter++;

                    throw new HttpRequestException();
                });
                return(messageHandler);
            };

            using (var kernel =
                       new TestingKernel <ConsoleLog>(
                           k =>
            {
                k.Rebind <IDiscovery>().To <ServiceDiscovery.Rewrite.Discovery>().InSingletonScope();
                k.Rebind <Func <bool, string, HttpMessageHandler> >().ToMethod(c => messageHandlerFactory);
            }, dict)
                   )
            {
                var providerFactory = kernel.Get <Func <string, ServiceProxyProvider> >();
                var serviceProxy    = providerFactory("DemoService");
                serviceProxy.DefaultPort = port;

                //Disable  TracingContext.SetRequestID("1");

                CallContext.FreeNamedDataSlot("#ORL_RC");

                string overrideHost = "override-host";
                int    overridePort = 5318;
                TracingContext.SetHostOverride("DemoService", overrideHost, overridePort);

                var request = new HttpServiceRequest("testMethod", null, new Dictionary <string, object>());

                for (int i = 0; i < 3; i++)
                {
                    Func <Task> act = () => serviceProxy.Invoke(request, typeof(string));

                    await act.ShouldThrowAsync <HttpRequestException>();
                }
                counter.ShouldBe(3);
            }
        }
示例#12
0
        public async Task HttpsListening_CallHttpsAfterFirstHttpCall()
        {
            var host            = "host1";
            var httpsPortOffset = 5;
            var port            = DisposablePort.GetPort().Port;
            var dict            = new Dictionary <string, string>
            {
                { "Discovery.Services.DemoService.Source", "Config" },
                { "Discovery.Services.DemoService.Hosts", host },
                { "Discovery.Services.DemoService.DefaultPort", port.ToString() },
                { "Discovery.Services.DemoService.TryHttps", "true" }
            };

            int httpsTestCount = 0;

            Func <HttpClientConfiguration, HttpMessageHandler> messageHandlerFactory = _ =>
            {
                var messageHandler = new MockHttpMessageHandler();
                messageHandler
                .When("https://*")
                .Respond(req =>
                {
                    if (req.RequestUri.AbsoluteUri == $"https://{host}:{port + httpsPortOffset}/")
                    {
                        httpsTestCount++;
                        return(HttpResponseFactory.GetResponse(content: "'some HTTPS response'"));
                    }
                    if (req.RequestUri.AbsoluteUri == $"https://{host}:{port + httpsPortOffset}/DemoService.testMethod")
                    {
                        return(HttpResponseFactory.GetResponse(content: "'some HTTPS response'"));
                    }
                    throw new HttpRequestException("Invalid uri");
                });
                messageHandler
                .When("http://*")
                .Respond(req =>
                {
                    if (req.RequestUri.AbsoluteUri == $"http://{host}:{port}/DemoService.testMethod")
                    {
                        return(HttpResponseFactory.GetResponse(content: "'some HTTP response'"));
                    }
                    throw new HttpRequestException("Invalid uri");
                });

                return(messageHandler);
            };

            using (var kernel =
                       new TestingKernel <ConsoleLog>(
                           k =>
            {
                k.Rebind <IDiscovery>().To <ServiceDiscovery.Rewrite.Discovery>().InSingletonScope();
                k.Rebind <Func <HttpClientConfiguration, HttpMessageHandler> >().ToMethod(c => messageHandlerFactory);
                var getConfig = k.Get <Func <DiscoveryConfig> >();
                k.Rebind <Func <DiscoveryConfig> >().ToMethod(c =>
                {
                    var config = getConfig();
                    return(() => config);
                });
            }, dict)
                   )
            {
                var providerFactory = kernel.Get <Func <string, ServiceProxyProvider> >();
                var serviceProxy    = providerFactory("DemoService");
                serviceProxy.DefaultPort = port;
                TracingContext.SetRequestID("1");

                var request = new HttpServiceRequest("testMethod", null, new Dictionary <string, object>());

                for (int i = 0; i < 10; i++)
                {
                    bool httpsTestFinished = httpsTestCount > 0;

                    var server = await serviceProxy.Invoke(request, typeof(string));

                    server.ShouldBe(httpsTestFinished ? "some HTTPS response" : "some HTTP response");
                }

                Assert.That(() => httpsTestCount, Is.EqualTo(1).After(10).Seconds.PollEvery(1).Seconds);
            }
        }
示例#13
0
        public async Task ServiceProxyRpcMessageShouldRemainSame()
        {
            const string serviceName = "DemoService";
            int          defaultPort = DisposablePort.GetPort().Port;
            var          dict        = new Dictionary <string, string>
            {
                { $"Discovery.Services.{serviceName}.Source", "Config" },
                { $"Discovery.Services.{serviceName}.Hosts", "host1" },
                { $"Discovery.Services.{serviceName}.DefaultPort", defaultPort.ToString() }
            };

            Uri    uri            = null;
            string requestMessage = null;

            Func <HttpClientConfiguration, HttpMessageHandler> messageHandlerFactory = _ =>
            {
                var messageHandler = new MockHttpMessageHandler();
                messageHandler
                .When("*").Respond(async req =>
                {
                    requestMessage = await req.Content.ReadAsStringAsync();
                    uri            = req.RequestUri;
                    return(HttpResponseFactory.GetResponse(HttpStatusCode.Accepted));
                });
                return(messageHandler);
            };

            using (var kernel = new TestingKernel <ConsoleLog>(k =>
            {
                k.Rebind <IDiscovery>().To <ServiceDiscovery.Rewrite.Discovery>().InSingletonScope();
                k.Rebind <Func <HttpClientConfiguration, HttpMessageHandler> >().ToMethod(c => messageHandlerFactory);
            }, dict))
            {
                var providerFactory = kernel.Get <Func <string, ServiceProxyProvider> >();

                TracingContext.SetRequestID("g");

                var serviceProxy = providerFactory(serviceName);

                string expectedHost = "override-host";
                int    expectedPort = DisposablePort.GetPort().Port;

                TracingContext.SetHostOverride(serviceName, expectedHost, expectedPort);

                var request = new HttpServiceRequest("testMethod", null, new Dictionary <string, object>());
                using (TracingContext.Tags.SetUnencryptedTag("test", 1))
                    using (TracingContext.SuppressCaching(CacheSuppress.RecursiveAllDownstreamServices))
                        await serviceProxy.Invoke(request, typeof(string));

                var body = requestMessage;
                Console.WriteLine($"error: {body}");

                JsonConvert.DeserializeObject <GigyaRequestProtocol>(body, new JsonSerializerSettings()
                {
                    MissingMemberHandling = MissingMemberHandling.Error
                });

                uri.Host.ShouldBe(expectedHost);
                uri.Port.ShouldBe(expectedPort);
            }
        }
 private Task <T> SendRequest <T>(HttpServiceRequest requestMessage)
 {
     return(this.httpService.SendRequestAsync <T>(requestMessage));
 }
示例#15
0
        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
                if (await TryHandleSpecialEndpoints(context))
                {
                    return;
                }

                // Regular endpoint handling
                using (_activeRequestsCounter.NewContext("Request"))
                {
                    RequestTimings.GetOrCreate(); // initialize request timing context

                    string methodName = null;
                    // Initialize with empty object for protocol backwards-compatibility.

                    var requestData = new HttpServiceRequest {
                        TracingData = new TracingData()
                    };
                    object[]         argumentsWithDefaults = null;
                    ServiceMethod    serviceMethod         = null;
                    ServiceCallEvent callEvent             = _serverRequestPublisher.GetNewCallEvent();
                    try
                    {
                        try
                        {
                            ValidateRequest(context);
                            await CheckSecureConnection(context);

                            requestData = await ParseRequest(context);


                            //-----------------------------------------------------------------------------------------
                            // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes
                            //-----------------------------------------------------------------------------------------
                            TracingContext.SetRequestID(requestData.TracingData.RequestID);
                            TracingContext.SpanStartTime    = requestData.TracingData.SpanStartTime;
                            TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy;
                            TracingContext.SetSpan(null, requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N"));

                            SetCallEventRequestData(callEvent, requestData);

                            TracingContext.SetOverrides(requestData.Overrides);

                            serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target);
                            callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name;
                            methodName = serviceMethod.ServiceInterfaceMethod.Name;
                            var arguments = requestData.Target.IsWeaklyTyped ? GetParametersByName(serviceMethod, requestData.Arguments) : requestData.Arguments.Values.Cast <object>().ToArray();
                            argumentsWithDefaults = GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments);
                        }
                        catch (Exception e)
                        {
                            callEvent.Exception = e;
                            if (e is RequestException)
                            {
                                throw;
                            }

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

                        RejectRequestIfLateOrOverloaded();

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

                        if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent))
                        {
                            callEvent.ErrCode = 0;
                            _successCounter.Increment();
                        }
                        else
                        {
                            _failureCounter.Increment();
                        }
                    }
                    catch (Exception e)
                    {
                        callEvent.Exception = callEvent.Exception ?? e;
                        _failureCounter.Increment();
                        Exception ex   = GetRelevantException(e);
                        string    json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex));
                        await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent);
                    }
                    finally
                    {
                        sw.Stop();
                        callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds;

                        _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);
                        }

                        _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod);
                    }
                }
            }
        }
        private async Task <string> GetResponse(HttpListenerContext context, ServiceMethod serviceMethod, HttpServiceRequest requestData)
        {
            string           response;
            InvocationResult invocationResult;

            if (requestData.Target.IsWeaklyTyped)
            {
                invocationResult = await Activator.Invoke(serviceMethod, requestData.Arguments);

                response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, serviceMethod.ServiceInterfaceMethod.ReturnType, JsonSettingsWeak));
            }
            else
            {
                invocationResult = await Activator.Invoke(serviceMethod, requestData.Arguments.Values.Cast <object>().ToArray());

                response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, serviceMethod.ServiceInterfaceMethod.ReturnType, JsonSettings));
            }

            context.Response.Headers.Add(GigyaHttpHeaders.ExecutionTime, invocationResult.ExecutionTime.ToString());

            return(response);
        }