Exemple #1
0
        private async Task HandleConfigurationRequestAsync(RequestContext ctx, IOnPremiseTargetRequestInternal request)
        {
            _logger?.Debug("Received configuration request from RelayServer. request-id={RequestId}", request.RequestId);

            using (var sr = new JsonTextReader(new StreamReader(new MemoryStream(request.Body))))
            {
                var config = JsonSerializer.Deserialize <ServerSideLinkConfiguration>(sr);

                TokenRefreshWindow = config.TokenRefreshWindow ?? TokenRefreshWindow;
                HeartbeatInterval  = config.HeartbeatInterval ?? HeartbeatInterval;

                _minReconnectWaitTime = config.ReconnectMinWaitTime ?? _minReconnectWaitTime;
                _maxReconnectWaitTime = config.ReconnectMaxWaitTime ?? _maxReconnectWaitTime;
                _logSensitiveData     = config.LogSensitiveData ?? _logSensitiveData;

                AbsoluteConnectionLifetime = config.AbsoluteConnectionLifetime ?? AbsoluteConnectionLifetime;
                SlidingConnectionLifetime  = config.SlidingConnectionLifetime ?? SlidingConnectionLifetime;

                _logger?.Debug("Applied configuration from RelayServer. configuration={@Configuration}", config);
            }

            var response = BuildDefaultResponse(request.OriginId, request.RequestId);

            try
            {
                // No cancellation token here, to not cancel sending of an already fetched response
                await PostResponseAsync(ctx, response, CancellationToken.None).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error during posting configuration response to relay. request-id={RequestId}", request.RequestId);
            }
        }
Exemple #2
0
        private async Task RequestLocalTargetAsync(RequestContext ctx, string key, IOnPremiseTargetConnector connector, IOnPremiseTargetRequestInternal request, CancellationToken cancellationToken)
        {
            var uri = new Uri(new Uri("http://local-target/"), request.Url);

            _logger?.Debug("Relaying request to local target. request-id={RequestId}, request-url={RequestUrl}", request.RequestId, _logSensitiveData ? uri.PathAndQuery : uri.AbsolutePath);

            var url = (request.Url.Length > key.Length) ? request.Url.Substring(key.Length + 1) : String.Empty;

            if (request.Body != null)
            {
                if (request.Body.Length == 0)
                {
                    // a length of 0 indicates that there is a larger body available on the server
                    _logger?.Verbose("Requesting body. request-id={RequestId}", request.RequestId);
                    // request the body from the RelayServer (because SignalR cannot handle large messages)
                    var webResponse = await GetToRelayAsync("/request/" + request.RequestId, cancellationToken).ConfigureAwait(false);

                    request.Stream = await webResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);                     // this stream should not be disposed (owned by the Framework)
                }
                else
                {
                    // the body is small enough to be used directly
                    request.Stream = new MemoryStream(request.Body);
                }
            }
            else
            {
                // no body available (e.g. GET request)
                request.Stream = Stream.Null;
            }

            if (request.Stream.CanSeek && request.Stream.Position != 0)
            {
                request.Stream.Position = 0;
            }

            using (var response = await GetResponseFromLocalTargetAsync(connector, url, request, RelayedRequestHeader).ConfigureAwait(false))
            {
                _logger?.Debug("Sending response. request-id={RequestId}", request.RequestId);

                try
                {
                    // transfer the result to the RelayServer (need POST here, because SignalR does not handle large messages)
                    await PostResponseAsync(ctx, response, cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger?.Error(ex, "Error during posting local target response to relay. request-id={RequestId}", request.RequestId);
                }
            }
        }
Exemple #3
0
        protected override async void OnMessageReceived(JToken message)
        {
            IOnPremiseTargetRequestInternal request = null;
            var startDate = DateTime.UtcNow;

            var ctx = new RequestContext();

            try
            {
                _logger?.Verbose("Received message from server. connection-id={ConnectionId}, message={Message}", ConnectionId, message);

                request = message.ToObject <OnPremiseTargetRequest>();
                request.ConnectionId = ConnectionId;

                try
                {
                    if (request.IsConfigurationRequest)
                    {
                        await HandleConfigurationRequestAsync(ctx, request).ConfigureAwait(false);

                        return;
                    }

                    if (request.IsPingRequest)
                    {
                        await HandlePingRequestAsync(ctx, request).ConfigureAwait(false);

                        return;
                    }

                    if (request.IsHeartbeatRequest)
                    {
                        await HandleHeartbeatRequestAsync(ctx, request).ConfigureAwait(false);

                        return;
                    }
                }
                finally
                {
                    await AcknowledgeRequestAsync(request).ConfigureAwait(false);
                }

                var key = request.Url.Split('/').FirstOrDefault();
                if (key != null)
                {
                    if (_connectors.TryGetValue(key, out var connector))
                    {
                        _logger?.Verbose("Found on-premise target and sending request. request-id={RequestId}, on-premise-key={OnPremiseTargetKey}", request.RequestId, key);

                        LastActivity = DateTime.UtcNow;

                        await RequestLocalTargetAsync(ctx, key, connector, request, CancellationToken.None).ConfigureAwait(false);                         // TODO no cancellation token here?

                        return;
                    }
                }

                _logger?.Information("No connector found for local server for request {RequestId} and url {RequestUrl}", request.RequestId, request.Url);
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error during handling received message. connection-id={ConnectionId}, message={Message}", ConnectionId, message);
            }
            finally
            {
                if (!ctx.IsRelayServerNotified && request != null)
                {
                    _logger?.Warning("Unhandled request. connection-id={ConnectionId}, request-id={RequestId}, message={message}", ConnectionId, request.RequestId, message);

                    var response = new OnPremiseTargetResponse()
                    {
                        RequestStarted  = startDate,
                        RequestFinished = DateTime.UtcNow,
                        StatusCode      = HttpStatusCode.NotFound,
                        OriginId        = request.OriginId,
                        RequestId       = request.RequestId,
                        HttpHeaders     = new Dictionary <string, string>(),
                    };

                    try
                    {
                        // No cancellation token here, to not cancel sending of an already fetched response
                        await PostResponseAsync(ctx, response, CancellationToken.None).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        _logger?.Error(ex, "Error during posting unhandled request response to relay. request-id={RequestId}", request.RequestId);
                    }
                }
            }
        }