Beispiel #1
0
        private async Task HandleHeartbeatRequestAsync(RequestContext ctx, IOnPremiseTargetRequest request)
        {
            _logger?.Debug("Received heartbeat from RelayServer. request-id={RequestId}", request.RequestId);

            if (LastHeartbeat == DateTime.MinValue)
            {
                if (request.HttpHeaders != null)
                {
                    request.HttpHeaders.TryGetValue("X-TTRELAY-HEARTBEATINTERVAL", out var heartbeatHeaderValue);
                    if (Int32.TryParse(heartbeatHeaderValue, out var heartbeatInterval))
                    {
                        _logger?.Information("Heartbeat interval set to {HeartbeatInterval} seconds", heartbeatInterval);
                        HeartbeatInterval = TimeSpan.FromSeconds(heartbeatInterval);
                    }
                }
            }

            LastHeartbeat = DateTime.UtcNow;
            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 heartbeat response to relay. request-id={RequestId}", request.RequestId);
            }
        }
Beispiel #2
0
        private async Task AcknowledgeRequestAsync(IOnPremiseTargetRequest request)
        {
            if (request.AcknowledgmentMode == AcknowledgmentMode.Auto)
            {
                _logger?.Debug("Automatically acknowledged by RelayServer. request-id={RequestId}", request.RequestId);
                return;
            }

            if (String.IsNullOrEmpty(request.AcknowledgeId))
            {
                _logger?.Debug("No acknowledgment possible. request-id={RequestId}, acknowledgment-mode={AcknowledgmentMode}", request.RequestId, request.AcknowledgmentMode);
                return;
            }

            switch (request.AcknowledgmentMode)
            {
            case AcknowledgmentMode.Default:
                _logger?.Debug("Sending acknowledge to RelayServer. request-id={RequestId}, origin-id={OriginId}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgeOriginId, request.AcknowledgeId);
                await SendAcknowledgmentAsync(request.AcknowledgeOriginId, request.AcknowledgeId).ConfigureAwait(false);

                break;

            case AcknowledgmentMode.Manual:
                _logger?.Debug("Manual acknowledgment needed. request-id={RequestId}, origin-id={OriginId}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgeOriginId, request.AcknowledgeId);
                break;

            default:
                _logger?.Warning("Unknown acknowledgment mode found. request-id={RequestId}, acknowledgment-mode={AcknowledgmentMode}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgmentMode, request.AcknowledgeId);
                break;
            }
        }
Beispiel #3
0
        private async Task AcknowledgeRequest(IOnPremiseTargetRequest request)
        {
            if (request.AcknowledgmentMode == AcknowledgmentMode.Auto)
            {
                _logger?.Debug("Automatically acknowledged by RelayServer. request-id={RequestId}", request.RequestId);
                return;
            }

            if (String.IsNullOrEmpty(request.AcknowledgeId))
            {
                _logger?.Debug("No acknowledgment possible. request-id={RequestId}, acknowledgment-mode={AcknowledgmentMode}", request.RequestId, request.AcknowledgmentMode);
                return;
            }

            switch (request.AcknowledgmentMode)
            {
            case AcknowledgmentMode.Default:
                _logger?.Debug("Sending acknowledge to RelayServer. request-id={RequestId}, origin-id={OriginId}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgeOriginId, request.AcknowledgeId);
                await GetToRelay($"/request/acknowledge?oid={request.AcknowledgeOriginId}&aid={request.AcknowledgeId}&cid={ConnectionId}", CancellationToken.None).ConfigureAwait(false);                         // TODO no cancellation token here?

                break;

            case AcknowledgmentMode.Manual:
                _logger?.Debug("Manual acknowledgment needed. request-id={RequestId}, origin-id={OriginId}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgeOriginId, request.AcknowledgeId);
                break;

            default:
                _logger?.Warning("Unknown acknowledgment mode found. request-id={RequestId}, acknowledgment-mode={AcknowledgmentMode}, acknowledge-id={AcknowledgeId}", request.RequestId, request.AcknowledgmentMode, request.AcknowledgeId);
                break;
            }
        }
 public InterceptedRequest(IOnPremiseTargetRequest request)
 {
     RequestId           = request.RequestId;
     OriginId            = request.OriginId;
     AcknowledgeId       = request.AcknowledgeId;
     HttpMethod          = request.HttpMethod;
     Url                 = request.Url;
     HttpHeaders         = request.HttpHeaders;
     Stream              = request.Stream;
     AcknowledgmentMode  = request.AcknowledgmentMode;
     AcknowledgeOriginId = request.AcknowledgeOriginId;
 }
Beispiel #5
0
        private async Task HandlePingRequestAsync(IOnPremiseTargetRequest request)
        {
            _logger.Info("Received ping from server");

            await PostToRelayAsync(() => new StringContent(JsonConvert.SerializeObject(new OnPremiseTargetReponse
            {
                RequestStarted = DateTime.UtcNow,
                RequestFinished = DateTime.UtcNow,
                StatusCode = HttpStatusCode.OK,
                OriginId = request.OriginId,
                RequestId = request.RequestId
            }), Encoding.UTF8, "application/json"));
        }
Beispiel #6
0
        private async Task HandlePingRequestAsync(RequestContext ctx, IOnPremiseTargetRequest request)
        {
            _logger?.Debug("Received ping from RelayServer. request-id={RequestId}", request.RequestId);
            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 ping response to relay. request-id={RequestId}", request.RequestId);
            }
        }
Beispiel #7
0
        private async Task <InterceptedResponse> GetResponseFromLocalTargetAsync(IOnPremiseTargetConnector connector, string url, IOnPremiseTargetRequest onPremiseTargetRequest, string relayedRequestHeader)
        {
            var request = new InterceptedRequest(onPremiseTargetRequest);

            try
            {
                var requestInterceptor = _onPremiseInterceptorFactory.CreateOnPremiseRequestInterceptor();
                requestInterceptor?.HandleRequest(request);
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error during intercepting the request. request-id={RequestId}", request.RequestId);
            }

            var onPremiseTargetResponse = await connector.GetResponseFromLocalTargetAsync(url, request, relayedRequestHeader).ConfigureAwait(false);

            var response = new InterceptedResponse(onPremiseTargetResponse);

            try
            {
                var responseInterceptor = _onPremiseInterceptorFactory.CreateOnPremiseResponseInterceptor();
                responseInterceptor?.HandleResponse(request, response);
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error during intercepting the response. request-id={RequestId}", request.RequestId);
            }

            return(response);
        }
Beispiel #8
0
        public async Task <IOnPremiseTargetReponse> GetResponseAsync(string url, IOnPremiseTargetRequest onPremiseTargetRequest)
        {
            _logger.Debug("Requesting response from On-Premise Target...");
            _logger.Trace("Requesting response from On-Premise Target. url={0}, request-id={1}, origin-id", url, onPremiseTargetRequest.RequestId, onPremiseTargetRequest.OriginId);

            var onPremiseTargetReponse = new OnPremiseTargetReponse
            {
                RequestId      = onPremiseTargetRequest.RequestId,
                OriginId       = onPremiseTargetRequest.OriginId,
                RequestStarted = DateTime.UtcNow
            };

            var webRequest = await CreateOnPremiseTargetWebRequestAsync(url, onPremiseTargetRequest);

            HttpWebResponse webResponse = null;

            try
            {
                try
                {
                    webResponse = (HttpWebResponse)await webRequest.GetResponseAsync();
                }
                catch (WebException wex)
                {
                    _logger.Trace("Error requesting response. request-id={0}", wex, onPremiseTargetRequest.RequestId);

                    if (wex.Status == WebExceptionStatus.ProtocolError)
                    {
                        webResponse = (HttpWebResponse)wex.Response;
                    }
                }

                if (webResponse == null)
                {
                    _logger.Warn("Gateway timeout!");
                    _logger.Trace("Gateway timeout. request-id={0}", onPremiseTargetRequest.RequestId);

                    onPremiseTargetReponse.StatusCode  = HttpStatusCode.GatewayTimeout;
                    onPremiseTargetReponse.HttpHeaders = new Dictionary <string, string>
                    {
                        { "X-TTRELAY-TIMEOUT", "On-Premise Target" }
                    };
                }
                else
                {
                    onPremiseTargetReponse.StatusCode = webResponse.StatusCode;

                    using (var stream = new MemoryStream())
                    {
                        onPremiseTargetReponse.HttpHeaders = webResponse.Headers.AllKeys.ToDictionary(n => n, n => webResponse.Headers.Get(n), StringComparer.OrdinalIgnoreCase);

                        using (var responseStream = webResponse.GetResponseStream() ?? Stream.Null)
                        {
                            await responseStream.CopyToAsync(stream);
                        }

                        onPremiseTargetReponse.Body = stream.ToArray();
                    }
                }

                onPremiseTargetReponse.RequestFinished = DateTime.UtcNow;

                _logger.Trace("Got response. status-code={0}, request-id={1}", onPremiseTargetReponse.StatusCode, onPremiseTargetReponse.RequestId);

                return(onPremiseTargetReponse);
            }
            finally {
                webResponse?.Dispose();
            }
        }
Beispiel #9
0
        private async Task <HttpWebRequest> CreateOnPremiseTargetWebRequestAsync(string url, IOnPremiseTargetRequest onPremiseTargetRequest)
        {
            _logger.Trace("Creating web request");

            var webRequest = WebRequest.CreateHttp(new Uri(BaseUri, url));

            webRequest.Method  = onPremiseTargetRequest.HttpMethod;
            webRequest.Timeout = _requestTimeout * 1000;

            foreach (var httpHeader in onPremiseTargetRequest.HttpHeaders)
            {
                _logger.Trace("   adding header: header={0}, value={1}", httpHeader.Key, httpHeader.Value);

                Action <HttpWebRequest, string> restrictedHeader;
                if (_requestHeaderTransformations.TryGetValue(httpHeader.Key, out restrictedHeader))
                {
                    restrictedHeader?.Invoke(webRequest, httpHeader.Value);
                }
                else
                {
                    webRequest.Headers.Add(httpHeader.Key, httpHeader.Value);
                }
            }

            if (onPremiseTargetRequest.Body != null)
            {
                _logger.Trace("   adding request body, length={0}", onPremiseTargetRequest.Body.Length);

                var requestStream = await webRequest.GetRequestStreamAsync();

                await requestStream.WriteAsync(onPremiseTargetRequest.Body, 0, onPremiseTargetRequest.Body.Length);

                await requestStream.FlushAsync();
            }

            return(webRequest);
        }
Beispiel #10
0
        public async Task <IOnPremiseTargetResponse> GetResponseFromLocalTargetAsync(string url, IOnPremiseTargetRequest request, string relayedRequestHeader)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            _logger?.Verbose("Requesting response from on-premise in-proc target. request-id={RequestId}, url={RequestUrl}, origin-id={OriginId}", request.RequestId, url, request.OriginId);

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

            try
            {
                var handler = CreateHandler();

                try
                {
                    using (var cts = new CancellationTokenSource(_requestTimeout))
                    {
                        await handler.ProcessRequest(request, response, cts.Token).ConfigureAwait(false);

                        if (cts.IsCancellationRequested)
                        {
                            _logger?.Warning("Gateway timeout. request-id={RequestId}", request.RequestId);

                            response.StatusCode  = HttpStatusCode.GatewayTimeout;
                            response.HttpHeaders = new Dictionary <string, string> {
                                ["X-TTRELAY-TIMEOUT"] = "On-Premise Target"
                            };
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger?.Debug(ex, "Error requesting response from in-proc target. request-id={RequestId}", request.RequestId);

                    response.StatusCode  = HttpStatusCode.InternalServerError;
                    response.HttpHeaders = new Dictionary <string, string> {
                        ["Content-Type"] = "text/plain"
                    };
                    response.Stream = new MemoryStream(Encoding.UTF8.GetBytes(ex.ToString()));
                }
                finally
                {
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    (handler as IDisposable)?.Dispose();
                }
            }
            catch (Exception ex)
            {
                _logger?.Warning(ex, "Error creating in-proc handler. request-id={RequestId}", request.RequestId);

                response.StatusCode  = HttpStatusCode.InternalServerError;
                response.HttpHeaders = new Dictionary <string, string> {
                    ["Content-Type"] = "text/plain"
                };
                response.Stream = new MemoryStream(Encoding.UTF8.GetBytes(ex.ToString()));
            }

            response.RequestFinished = DateTime.UtcNow;

            _logger?.Verbose("Got in-proc response. request-id={RequestId}, status-code={ResponseStatusCode}", response.RequestId, response.StatusCode);

            return(response);
        }
Beispiel #11
0
        private async Task <HttpResponseMessage> SendLocalRequestAsync(String url, IOnPremiseTargetRequest request, String relayedRequestHeader, CancellationToken token)
        {
            var requestMessage = _requestMessageBuilder.CreateLocalTargetRequestMessage(_baseUri, url, request, relayedRequestHeader);

            return(await _httpClient.SendAsync(requestMessage, token).ConfigureAwait(false));
        }
Beispiel #12
0
        private async Task <HttpResponseMessage> SendLocalRequestWithTimeoutAsync(String url, IOnPremiseTargetRequest request, String relayedRequestHeader)
        {
            // Only create CTS when really required (i.e. Timeout not Zero or infinite)
            if (_requestTimeout > TimeSpan.Zero && _requestTimeout != TimeSpan.MaxValue)
            {
                using (var cts = new CancellationTokenSource(_requestTimeout))
                {
                    return(await SendLocalRequestAsync(url, request, relayedRequestHeader, cts.Token).ConfigureAwait(false));
                }
            }

            return(await SendLocalRequestAsync(url, request, relayedRequestHeader, CancellationToken.None).ConfigureAwait(false));
        }
Beispiel #13
0
        public async Task <IOnPremiseTargetResponse> GetResponseFromLocalTargetAsync(string url, IOnPremiseTargetRequest request, string relayedRequestHeader)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            _logger?.Verbose("Requesting response from on-premise web target. request-id={RequestId}, url={RequestUrl}, origin-id={OriginId}", request.RequestId, url, request.OriginId);

            var response = new OnPremiseTargetResponse()
            {
                RequestId      = request.RequestId,
                OriginId       = request.OriginId,
                RequestStarted = DateTime.UtcNow,
            };

            try
            {
                var message = await SendLocalRequestWithTimeoutAsync(url, request, relayedRequestHeader).ConfigureAwait(false);

                response.StatusCode  = message.StatusCode;
                response.HttpHeaders = message.Headers.Union(message.Content.Headers).ToDictionary(kvp => kvp.Key, kvp => String.Join(" ", kvp.Value));
                response.Stream      = await message.Content.ReadAsStreamAsync().ConfigureAwait(false);

                response.HttpResponseMessage = message;
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "Error requesting response from local target. request-id={RequestId}", request.RequestId);

                response.StatusCode  = HttpStatusCode.GatewayTimeout;
                response.HttpHeaders = new Dictionary <string, string> {
                    ["X-TTRELAY-TIMEOUT"] = "On-Premise Target"
                };
            }

            response.RequestFinished = DateTime.UtcNow;

            _logger?.Verbose("Got web response. request-id={RequestId}, status-code={ResponseStatusCode}", response.RequestId, response.StatusCode);

            return(response);
        }