Esempio n. 1
0
        private async Task SendHeartbeatAsync(IOnPremiseConnectionContext connectionContext, CancellationToken token)
        {
            if (connectionContext == null)
            {
                throw new ArgumentNullException(nameof(connectionContext));
            }

            if (connectionContext.NextHeartbeat > DateTime.UtcNow)
            {
                return;
            }

            connectionContext.NextHeartbeat = DateTime.UtcNow.Add(_heartbeatInterval);

            try
            {
                _logger?.Verbose("Sending {PingMethod}. connection-id={ConnectionId}", connectionContext.SupportsHeartbeat ? "Heartbeat" : "Ping (as heartbeat)", connectionContext.ConnectionId);

                var requestId = Guid.NewGuid().ToString();
                var request   = new OnPremiseConnectorRequest()
                {
                    HttpMethod         = connectionContext.SupportsHeartbeat ? "HEARTBEAT" : "PING",
                    Url                = String.Empty,
                    RequestStarted     = DateTime.UtcNow,
                    OriginId           = _backendCommunication.OriginId,
                    RequestId          = requestId,
                    AcknowledgmentMode = AcknowledgmentMode.Auto,
                    HttpHeaders        = connectionContext.SupportsConfiguration ? null : new Dictionary <string, string> {
                        ["X-TTRELAY-HEARTBEATINTERVAL"] = _heartbeatInterval.TotalSeconds.ToString(CultureInfo.InvariantCulture)
                    },
                };

                // wait for the response of the Heartbeat / Ping
                var task = _backendCommunication.GetResponseAsync(requestId, _configuration.ActiveConnectionTimeout);

                // heartbeats do NOT go through the message dispatcher as we want to heartbeat the connections directly
                await connectionContext.RequestAction(request, token).ConfigureAwait(false);

                var response = await task.ConfigureAwait(false);

                if (response != null)
                {
                    await _backendCommunication.RenewLastActivityAsync(connectionContext.ConnectionId).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error during sending heartbeat to a client. link-id={LinkId}, connection-id={ConnectionId}, connector-version={ConnectorVersion}", connectionContext.LinkId, connectionContext.ConnectionId, connectionContext.ConnectorVersion);
            }
        }
Esempio n. 2
0
        public async Task <IHttpActionResult> PingAsync(Guid id)
        {
            var requestId = Guid.NewGuid().ToString();
            var onPremiseConnectorRequest = new OnPremiseConnectorRequest
            {
                HttpMethod     = "PING",
                Url            = "",
                RequestStarted = DateTime.UtcNow,
                OriginId       = _backendCommunication.OriginId,
                RequestId      = requestId
            };

            await _backendCommunication.SendOnPremiseConnectorRequest(id.ToString(), onPremiseConnectorRequest);

            var onPremiseTargetReponse = await _backendCommunication.GetResponseAsync(requestId);

            onPremiseConnectorRequest.RequestFinished = DateTime.UtcNow;

            _requestLogger.LogRequest(onPremiseConnectorRequest, onPremiseTargetReponse, HttpStatusCode.OK, id, _backendCommunication.OriginId, "invalid/Ping.local/");

            return(Ok());
        }
Esempio n. 3
0
        public async Task <IHttpActionResult> SendPing(Guid id)
        {
            var requestId = Guid.NewGuid().ToString();
            var request   = new OnPremiseConnectorRequest()
            {
                HttpMethod     = "PING",
                Url            = String.Empty,
                RequestStarted = DateTime.UtcNow,
                OriginId       = _backendCommunication.OriginId,
                RequestId      = requestId
            };

            var task = _backendCommunication.GetResponseAsync(requestId);

            _backendCommunication.SendOnPremiseConnectorRequest(id, request);

            var response = await task.ConfigureAwait(false);

            request.RequestFinished = DateTime.UtcNow;
            _requestLogger.LogRequest(request, response, id, _backendCommunication.OriginId, "DEBUG/PING/", response?.StatusCode);

            return((response != null) ? (IHttpActionResult)Ok() : new StatusCodeResult(HttpStatusCode.GatewayTimeout, Request));
        }
Esempio n. 4
0
        public async Task <HttpResponseMessage> Relay(string path)
        {
            _logger.Trace("Relaying http {0} {1}", path, ControllerContext.Request.Method);

            if (path == null)
            {
                _logger.Info("Path is not set.");
                return(NotFound());
            }

            var pathInformation = _pathSplitter.Split(path);
            var link            = _linkRepository.GetLink(pathInformation.UserName);

            if (link == null)
            {
                _logger.Info("Link for requested path {0} not found", path);
                return(NotFound());
            }

            if (link.IsDisabled)
            {
                _logger.Info("{0}: Link {1} is disabled", link.Id, link.SymbolicName);
                return(NotFound());
            }

            if (string.IsNullOrWhiteSpace(pathInformation.PathWithoutUserName))
            {
                _logger.Info("{0}: Path without username is not found. Wrong path information: {1}", link.Id, path);
                return(NotFound());
            }

            if (link.AllowLocalClientRequestsOnly && !Request.IsLocal())
            {
                _logger.Info("{0}: Link {1} only allows local requests.", link.Id, link.SymbolicName);
                return(NotFound());
            }

            _logger.Trace("{0}: Building on premise connector request. Origin Id: {1}, Path: {2}", link.Id, _backendCommunication.OriginId, path);
            var onPremiseConnectorRequest =
                (OnPremiseConnectorRequest)
                await _onPremiseRequestBuilder.BuildFrom(Request, _backendCommunication.OriginId, pathInformation.PathWithoutUserName);

            _logger.Trace("{0}: Sending on premise connector request.", link.Id);
            await _backendCommunication.SendOnPremiseConnectorRequest(link.Id.ToString(), onPremiseConnectorRequest);

            _logger.Trace("{0}: Waiting for response. Request Id", onPremiseConnectorRequest.RequestId);
            var onPremiseTargetReponse = await _backendCommunication.GetResponseAsync(onPremiseConnectorRequest.RequestId);

            if (onPremiseTargetReponse != null)
            {
                _logger.Trace("{0}: Response received from {1}", link.Id, onPremiseTargetReponse.RequestId);
            }
            else
            {
                _logger.Trace("{0}: On Premise Timeout", link.Id);
            }

            var response = _httpResponseMessageBuilder.BuildFrom(onPremiseTargetReponse, link);

            onPremiseConnectorRequest.RequestFinished = DateTime.UtcNow;

            var currentTraceConfigurationId = _traceManager.GetCurrentTraceConfigurationId(link.Id);

            if (currentTraceConfigurationId != null)
            {
                _traceManager.Trace(onPremiseConnectorRequest, onPremiseTargetReponse, currentTraceConfigurationId.Value);
            }

            _requestLogger.LogRequest(onPremiseConnectorRequest, onPremiseTargetReponse, response.StatusCode, link.Id, _backendCommunication.OriginId, path);

            return(response);
        }
        public async Task <HttpResponseMessage> Relay(string fullPathToOnPremiseEndpoint)
        {
            _logger?.Debug("Relaying request. method={RequestMethod}, path={RequestPath}", ControllerContext.Request.Method, fullPathToOnPremiseEndpoint);

            if (fullPathToOnPremiseEndpoint == null)
            {
                _logger?.Information("Path to on premise endpoint is not set");
                return(NotFound());
            }

            var pathInformation = _pathSplitter.Split(fullPathToOnPremiseEndpoint);
            var link            = _linkRepository.GetLink(pathInformation.UserName);

            if (!CanRequestBeHandled(fullPathToOnPremiseEndpoint, pathInformation, link))
            {
                _logger?.Information("Request cannot be handled");
                return(NotFound());
            }

            var request = await _onPremiseRequestBuilder.BuildFromHttpRequest(Request, _backendCommunication.OriginId, pathInformation.PathWithoutUserName).ConfigureAwait(false);

            var statusCode = HttpStatusCode.GatewayTimeout;
            IOnPremiseConnectorResponse response = null;

            try
            {
                request = _interceptorManager.HandleRequest(request, Request, User, out var message);
                if (message != null)
                {
                    _logger?.Verbose("Interceptor caused direct answering of request. request-id={RequestId}, status-code={ResponseStatusCode}", request.RequestId, message.StatusCode);

                    statusCode = message.StatusCode;

                    if (request.AlwaysSendToOnPremiseConnector)
                    {
                        _logger?.Verbose("Interceptor caused always sending of request. request-id={RequestId}", request.RequestId);
                        SendOnPremiseConnectorRequest(link.Id, request);
                    }

                    return(message);
                }

                var task = _backendCommunication.GetResponseAsync(request.RequestId);
                SendOnPremiseConnectorRequest(link.Id, request);

                _logger?.Verbose("Waiting for response. request-id={RequestId}, link-id={LinkId}", request.RequestId, link.Id);
                response = await task.ConfigureAwait(false);

                if (response != null)
                {
                    _logger?.Verbose("Response received. request-id={RequestId}, link-id={LinkId}", request.RequestId, link.Id);
                    FetchResponseBodyForIntercepting((OnPremiseConnectorResponse)response);
                    statusCode = response.StatusCode;
                }
                else
                {
                    _logger?.Verbose("No response received because of on-premise timeout. request-id={RequestId}, link-id={LinkId}", request.RequestId, link.Id);
                }

                return(_interceptorManager.HandleResponse(request, Request, User, response, link.ForwardOnPremiseTargetErrorResponse));
            }
            finally
            {
                FinishRequest(request as OnPremiseConnectorRequest, response, link.Id, fullPathToOnPremiseEndpoint, statusCode);
            }
        }