예제 #1
0
 internal void RemoveIgnoredHeaders(OnPremiseConnectorRequest onPremiseConnectorRequest)
 {
     foreach (var key in _ignoredHeaders)
     {
         onPremiseConnectorRequest.HttpHeaders.Remove(key);
     }
 }
        private async Task ProvideLinkConfigurationAsync(IOnPremiseConnectionContext onPremiseConnectionContext)
        {
            try
            {
                var config = _linkRepository.GetLinkConfiguration(onPremiseConnectionContext.LinkId);
                config.ApplyDefaults(_configuration);

                var requestId = Guid.NewGuid().ToString();

                _logger?.Debug("Sending configuration to OPC. connection-id={ConnectionId}, link-id={LinkId}, connector-version={ConnectorVersion}, link-configuration={@LinkConfiguration}, request-id={RequestId}", onPremiseConnectionContext.ConnectionId, onPremiseConnectionContext.LinkId, onPremiseConnectionContext.ConnectorVersion, config, requestId);

                var request = new OnPremiseConnectorRequest()
                {
                    HttpMethod         = "CONFIG",
                    Url                = String.Empty,
                    RequestStarted     = DateTime.UtcNow,
                    OriginId           = OriginId,
                    RequestId          = requestId,
                    AcknowledgmentMode = AcknowledgmentMode.Auto,
                    Body               = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(config)),
                };

                // configs, like heartbeats, do not go through the message dispatcher but directly to the connection
                await onPremiseConnectionContext.RequestAction(request, CancellationToken.None).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger?.Error(ex, "An error happened while sending the link config to the connected OPC.");
            }
        }
예제 #3
0
        public async Task Relay_delegates_information_and_returns_valid_httpResponseMessage_when_entered_a_valid_path()
        {
            var startTime  = DateTime.UtcNow;
            var loggerMock = new Mock <ILogger>();
            var backendCommunicationMock       = new Mock <IBackendCommunication>();
            var relayRepositoryMock            = new Mock <ILinkRepository>();
            var pathSplitterMock               = new Mock <IPathSplitter>();
            var clientRequestBuilderMock       = new Mock <IOnPremiseRequestBuilder>();
            var httpResponseMessageBuilderMock = new Mock <IHttpResponseMessageBuilder>();
            var requestLoggerMock              = new Mock <IRequestLogger>();
            var traceManagerMock               = new Mock <ITraceManager>();
            var sut = new ClientController(backendCommunicationMock.Object, loggerMock.Object, relayRepositoryMock.Object, requestLoggerMock.Object, httpResponseMessageBuilderMock.Object, clientRequestBuilderMock.Object, pathSplitterMock.Object, traceManagerMock.Object)
            {
                ControllerContext = new HttpControllerContext {
                    Request = new HttpRequestMessage {
                        Method = HttpMethod.Post
                    }
                },
                Request = new HttpRequestMessage()
            };
            HttpResponseMessage result;

            var linkFake = new Link {
                Id = Guid.Parse("fb35e2fb-5fb6-4475-baa0-e0b06f5fdeda")
            };
            var clientRequestFake = new OnPremiseConnectorRequest {
                RequestId = "239b6e03-9795-450d-bdd1-ab72900f1a98"
            };
            var onPremiseTargetReponseFake = new OnPremiseTargetReponse();
            var httpResponseMessageFake    = new HttpResponseMessage {
                StatusCode = HttpStatusCode.Found
            };
            var localConfigurationGuid = Guid.NewGuid();

            loggerMock.Setup(l => l.Trace(It.IsAny <string>));
            backendCommunicationMock.SetupGet(b => b.OriginId).Returns("c9208bdb-c195-460d-b84e-6c146bb252e5");
            relayRepositoryMock.Setup(l => l.GetLink(It.IsAny <string>())).Returns(linkFake);
            pathSplitterMock.Setup(p => p.Split(It.IsAny <string>())).Returns(new PathInformation {
                PathWithoutUserName = "******"
            });
            clientRequestBuilderMock.Setup(c => c.BuildFrom(sut.Request, "c9208bdb-c195-460d-b84e-6c146bb252e5", "Bar/Baz")).ReturnsAsync(clientRequestFake);
            backendCommunicationMock.Setup(b => b.SendOnPremiseConnectorRequest("fb35e2fb-5fb6-4475-baa0-e0b06f5fdeda", clientRequestFake)).Returns(Task.FromResult(0));
            backendCommunicationMock.Setup(b => b.GetResponseAsync("239b6e03-9795-450d-bdd1-ab72900f1a98")).ReturnsAsync(onPremiseTargetReponseFake);
            httpResponseMessageBuilderMock.Setup(h => h.BuildFrom(onPremiseTargetReponseFake, linkFake)).Returns(httpResponseMessageFake);
            traceManagerMock.Setup(t => t.GetCurrentTraceConfigurationId(linkFake.Id)).Returns(localConfigurationGuid);
            traceManagerMock.Setup(t => t.Trace(clientRequestFake, onPremiseTargetReponseFake, localConfigurationGuid));
            requestLoggerMock.Setup(r => r.LogRequest(clientRequestFake, onPremiseTargetReponseFake, HttpStatusCode.Found, Guid.Parse("fb35e2fb-5fb6-4475-baa0-e0b06f5fdeda"), "c9208bdb-c195-460d-b84e-6c146bb252e5", "Foo/Bar/Baz"));

            result = await sut.Relay("Foo/Bar/Baz");

            relayRepositoryMock.VerifyAll();
            pathSplitterMock.VerifyAll();
            backendCommunicationMock.VerifyAll();
            clientRequestBuilderMock.VerifyAll();
            httpResponseMessageBuilderMock.VerifyAll();
            requestLoggerMock.VerifyAll();
            traceManagerMock.VerifyAll();
            clientRequestFake.RequestFinished.Should().BeAfter(startTime).And.BeOnOrBefore(DateTime.UtcNow);
            result.Should().BeSameAs(httpResponseMessageFake);
        }
예제 #4
0
        public void LogRequest_writes_correctly_composed_log_entry_to_the_RelayRepository_when_OnPremiseTargetResult_is_null()
        {
            var            logRepositoryMock = new Mock <ILogRepository>();
            var            pathSplitterMock  = new Mock <IPathSplitter>();
            IRequestLogger sut           = new RequestLogger(logRepositoryMock.Object, pathSplitterMock.Object);
            var            clientRequest = new OnPremiseConnectorRequest
            {
                Body            = new byte[] { 0, 0, 0 },
                RequestStarted  = new DateTime(2014, 1, 1),
                RequestFinished = new DateTime(2014, 1, 2)
            };
            RequestLogEntry result = null;

            logRepositoryMock.Setup(r => r.LogRequest(It.IsAny <RequestLogEntry>())).Callback <RequestLogEntry>(r => result = r);
            pathSplitterMock.Setup(p => p.Split(It.IsAny <string>())).Returns(new PathInformation {
                OnPremiseTargetKey = "that", LocalUrl = "/file.html"
            });

            sut.LogRequest(clientRequest, null, HttpStatusCode.PaymentRequired, Guid.Parse("4bb4ff98-ba03-49ee-bd83-5a229f63fade"), "35eff886-2d7c-4265-a6a4-f3f471ab93e8", "gimme/that/file.html");

            logRepositoryMock.Verify(r => r.LogRequest(It.IsAny <RequestLogEntry>()));
            result.HttpStatusCode.Should().Be(HttpStatusCode.PaymentRequired);
            result.OriginId.Should().Be(Guid.Parse("35eff886-2d7c-4265-a6a4-f3f471ab93e8"));
            result.LocalUrl.Should().Be("/file.html");
            result.OnPremiseTargetKey.Should().Be("that");
            result.OnPremiseConnectorInDate.Should().Be(new DateTime(2014, 1, 1));
            result.OnPremiseConnectorOutDate.Should().Be(new DateTime(2014, 1, 2));
            result.OnPremiseTargetInDate.Should().Be(null);
            result.OnPremiseTargetOutDate.Should().Be(null);
            result.ContentBytesIn.Should().Be(3L);
            result.ContentBytesOut.Should().Be(0L);
            result.LinkId.Should().Be(Guid.Parse("4bb4ff98-ba03-49ee-bd83-5a229f63fade"));
        }
예제 #5
0
        public void Trace_logs_exception()
        {
            var traceFileWriterMock  = new Mock <ITraceFileWriter>();
            var loggerMock           = new Mock <ILogger>();
            var traceConfigurationId = Guid.NewGuid();
            var clientRequest        = new OnPremiseConnectorRequest
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "text/plain" },
                    { "Content-Length", "700" }
                },
                Body = new byte[] { 65, 66, 67 }
            };
            var onPremiseTargetResponse = new OnPremiseTargetReponse
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "image/png" },
                    { "Content-Length", "7500" }
                },
                Body = new byte[] { 66, 67, 68 }
            };
            ITraceManager sut = new TraceManager(null, traceFileWriterMock.Object, null, new Configuration(), loggerMock.Object);

            var exception = new Exception();

            traceFileWriterMock.Setup(t => t.WriteContentFile(It.IsAny <string>(), clientRequest.Body)).Throws(exception);
            loggerMock.Setup(l => l.Warn(It.IsAny <string>(), exception));

            sut.Trace(clientRequest, onPremiseTargetResponse, traceConfigurationId);

            traceFileWriterMock.VerifyAll();
        }
예제 #6
0
        public async Task Relay_delegates_information_and_returns_valid_httpResponseMessage_when_entered_a_valid_path()
        {
            var startTime = DateTime.UtcNow;
            var sut       = CreateClientController();

            sut.ControllerContext = new HttpControllerContext {
                Request = new HttpRequestMessage {
                    Method = HttpMethod.Post
                }
            };
            sut.Request = new HttpRequestMessage();
            sut.User    = new FakePrincipal();

            HttpResponseMessage result;

            var requestId = "239b6e03-9795-450d-bdd1-ab72900f1a98";
            var linkId    = new Guid("fb35e2fb-5fb6-4475-baa0-e0b06f5fdeda");
            var linkFake  = new Link {
                Id = linkId
            };
            var clientRequestFake = new OnPremiseConnectorRequest {
                RequestId = requestId
            };
            var onPremiseTargetResponseFake = new OnPremiseConnectorResponse();
            var httpResponseMessageFake     = new HttpResponseMessage {
                StatusCode = HttpStatusCode.Found
            };
            var localConfigurationGuid = Guid.NewGuid();
            var originId = new Guid("c9208bdb-c195-460d-b84e-6c146bb252e5");

            _loggerMock.Setup(l => l.Verbose(It.IsAny <string>()));
            _backendCommunicationMock.SetupGet(b => b.OriginId).Returns(originId);
            _relayRepositoryMock.Setup(l => l.GetLink(It.IsAny <string>())).Returns(linkFake);
            _pathSplitterMock.Setup(p => p.Split(It.IsAny <string>())).Returns(new PathInformation {
                PathWithoutUserName = "******"
            });
            _clientRequestBuilderMock.Setup(c => c.BuildFromHttpRequest(sut.Request, originId, "Bar/Baz")).ReturnsAsync(clientRequestFake);
            _backendCommunicationMock.Setup(b => b.SendOnPremiseConnectorRequest(linkId, clientRequestFake));
            _backendCommunicationMock.Setup(b => b.GetResponseAsync(requestId, null)).ReturnsAsync(onPremiseTargetResponseFake);
            _traceManagerMock.Setup(t => t.GetCurrentTraceConfigurationId(linkFake.Id)).Returns(localConfigurationGuid);
            _traceManagerMock.Setup(t => t.Trace(clientRequestFake, onPremiseTargetResponseFake, localConfigurationGuid));
            _requestLoggerMock.Setup(r => r.LogRequest(clientRequestFake, onPremiseTargetResponseFake, linkId, originId, "Foo/Bar/Baz", 0));
            HttpResponseMessage messageDummy;

            _interceptorManagerMock.Setup(i => i.HandleRequest(clientRequestFake, sut.Request, sut.User, out messageDummy)).Returns(clientRequestFake);
            _interceptorManagerMock.Setup(i => i.HandleResponse(clientRequestFake, sut.Request, sut.User, onPremiseTargetResponseFake, false)).Returns(httpResponseMessageFake);

            result = await sut.Relay("Foo/Bar/Baz");

            _relayRepositoryMock.VerifyAll();
            _pathSplitterMock.VerifyAll();
            _backendCommunicationMock.VerifyAll();
            _clientRequestBuilderMock.VerifyAll();
            _requestLoggerMock.VerifyAll();
            _traceManagerMock.VerifyAll();
            _interceptorManagerMock.VerifyAll();
            clientRequestFake.RequestFinished.Should().BeAfter(startTime).And.BeOnOrBefore(DateTime.UtcNow);
            result.Should().BeSameAs(httpResponseMessageFake);
        }
예제 #7
0
        private void FinishRequest(OnPremiseConnectorRequest request, IOnPremiseConnectorResponse response, LinkInformation link, string path, HttpStatusCode statusCode)
        {
            if (request == null)
            {
                return;
            }

            request.RequestFinished = DateTime.UtcNow;

            _logger?.Verbose("Finishing request. request-id={RequestId}, link-id={LinkId}, link-name={LinkName}, on-premise-duration={RemoteDuration}, global-duration={GlobalDuration}", request.RequestId, link.Id, link.SymbolicName, response?.RequestFinished - response?.RequestStarted, request.RequestFinished - request.RequestStarted);

            _traceManager.Trace(request, response, link.TraceConfigurationIds);
            _requestLogger.LogRequest(request, response, link.Id, _backendCommunication.OriginId, path, statusCode);
        }
예제 #8
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);
            }
        }
예제 #9
0
        public void Trace_uses_correct_file_names_build_from_Trace_ID_and_DateTime_ticks()
        {
            var traceFileWriterMock  = new Mock <ITraceFileWriter>();
            var loggerMock           = new Mock <ILogger>();
            var traceConfigurationId = Guid.NewGuid();
            var clientRequest        = new OnPremiseConnectorRequest
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "text/plain" },
                    { "Content-Length", "700" }
                },
                Body = new byte[] { 65, 66, 67 }
            };
            var onPremiseTargetResponse = new OnPremiseTargetReponse
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "image/png" },
                    { "Content-Length", "7500" }
                },
                Body = new byte[] { 66, 67, 68 }
            };
            string        clientRequestBodyFileName              = null;
            string        clientRequestHeadersFileName           = null;
            string        onPremiseTargetResponseBodyFileName    = null;
            string        onPremiseTargetResponseHeadersFileName = null;
            DateTime      startTime;
            ITraceManager sut = new TraceManager(null, traceFileWriterMock.Object, null, new Configuration(), loggerMock.Object);

            startTime = DateTime.Now;

            traceFileWriterMock.Setup(t => t.WriteContentFile(It.IsAny <string>(), clientRequest.Body)).Callback((string f, byte[] c) => clientRequestBodyFileName = f);
            traceFileWriterMock.Setup(t => t.WriteContentFile(It.IsAny <string>(), onPremiseTargetResponse.Body)).Callback((string f, byte[] c) => onPremiseTargetResponseBodyFileName            = f);;
            traceFileWriterMock.Setup(t => t.WriteHeaderFile(It.IsAny <string>(), clientRequest.HttpHeaders)).Callback((string f, IDictionary <string, string> c) => clientRequestHeadersFileName = f);;
            traceFileWriterMock.Setup(t => t.WriteHeaderFile(It.IsAny <string>(), onPremiseTargetResponse.HttpHeaders)).Callback((string f, IDictionary <string, string> c) => onPremiseTargetResponseHeadersFileName = f);;

            sut.Trace(clientRequest, onPremiseTargetResponse, traceConfigurationId);

            var ticks = new DateTime(long.Parse(clientRequestBodyFileName.Split('-').Skip(5).First().Split('.').First()));
            var expectedFileNamePrefix = Path.Combine("tracefiles", traceConfigurationId + "-" + ticks.Ticks);

            traceFileWriterMock.VerifyAll();
            ticks.Should().BeOnOrAfter(startTime).And.BeOnOrBefore(DateTime.Now);
            clientRequestBodyFileName.Should().Be(expectedFileNamePrefix + ".ct.content");
            onPremiseTargetResponseBodyFileName.Should().Be(expectedFileNamePrefix + ".optt.content");
            clientRequestHeadersFileName.Should().Be(expectedFileNamePrefix + ".ct.headers");
            onPremiseTargetResponseHeadersFileName.Should().Be(expectedFileNamePrefix + ".optt.headers");
        }
예제 #10
0
        private void PrepareRequestBodyForRelaying(OnPremiseConnectorRequest request)
        {
            if (request.Stream == null)
            {
                request.Body = null;
                return;
            }

            if (request.ContentLength == 0 || request.ContentLength >= 0x10000)
            {
                // We might have no Content-Length header, but still content, so we'll assume a large body first
                using (var storeStream = _postDataTemporaryStore.CreateRequestStream(request.RequestId))
                {
                    request.Stream.CopyTo(storeStream);
                    if (storeStream.Length < 0x10000)
                    {
                        if (storeStream.Length == 0)
                        {
                            // no body available (e.g. GET request)
                        }
                        else
                        {
                            // the body is small enough to be used directly
                            request.Body         = new byte[storeStream.Length];
                            storeStream.Position = 0;
                            storeStream.Read(request.Body, 0, (int)storeStream.Length);
                        }
                    }
                    else
                    {
                        // a length of 0 indicates that there is a larger body available on the server
                        request.Body = Array.Empty <byte>();
                    }

                    request.Stream        = null;
                    request.ContentLength = storeStream.Length;
                }
            }
            else
            {
                // we have a body, and it is small enough to be transmitted directly
                request.Body = new byte[request.ContentLength];
                request.Stream.Read(request.Body, 0, (int)request.ContentLength);
                request.Stream = null;
            }
        }
예제 #11
0
        public void RemoveIgnoredHeaders_removes_ignored_headers_from_ClientRequest()
        {
            var clientRequest = new OnPremiseConnectorRequest
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Host", "tt.invalid" },
                    { "Connection", "close" },
                    { "Content-Length", "3" }
                }
            };
            var sut = new OnPremiseRequestBuilder();

            sut.RemoveIgnoredHeaders(clientRequest);

            clientRequest.HttpHeaders.Should().HaveCount(1);
            clientRequest.HttpHeaders.Single().Key.Should().Be("Content-Length");
        }
예제 #12
0
        private void FinishRequest(OnPremiseConnectorRequest request, IOnPremiseConnectorResponse response, Guid linkId, string path, HttpStatusCode statusCode)
        {
            if (request == null)
            {
                return;
            }

            request.RequestFinished = DateTime.UtcNow;

            _logger?.Verbose("Finishing request. request-id={RequestId}, link-id={LinkId}, on-premise-duration={RemoteDuration}, global-duration={GlobalDuration}", request.RequestId, linkId, response?.RequestFinished - response?.RequestStarted, request.RequestFinished - request.RequestStarted);

            // TODO this may be debounced for e.g. 5 minutes to skip querying on each request in future release
            var currentTraceConfigurationId = _traceManager.GetCurrentTraceConfigurationId(linkId);

            if (currentTraceConfigurationId != null)
            {
                _traceManager.Trace(request, response, currentTraceConfigurationId.Value);
            }

            _requestLogger.LogRequest(request, response, linkId, _backendCommunication.OriginId, path, statusCode);
        }
예제 #13
0
        public void Trace_creates_tracefiles_directory()
        {
            var traceFileWriterMock  = new Mock <ITraceFileWriter>();
            var loggerMock           = new Mock <ILogger>();
            var traceConfigurationId = Guid.NewGuid();
            var clientRequest        = new OnPremiseConnectorRequest
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "text/plain" },
                    { "Content-Length", "700" }
                },
                Body = new byte[] { 65, 66, 67 }
            };
            var onPremiseTargetResponse = new OnPremiseTargetReponse
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Type", "image/png" },
                    { "Content-Length", "7500" }
                },
                Body = new byte[] { 66, 67, 68 }
            };
            ITraceManager sut = new TraceManager(null, traceFileWriterMock.Object, null, new Configuration(), loggerMock.Object);

            Directory.CreateDirectory("tracefiles");
            Directory.Delete("tracefiles");

            traceFileWriterMock.Setup(t => t.WriteContentFile(It.IsAny <string>(), clientRequest.Body));
            traceFileWriterMock.Setup(t => t.WriteContentFile(It.IsAny <string>(), onPremiseTargetResponse.Body));
            traceFileWriterMock.Setup(t => t.WriteHeaderFile(It.IsAny <string>(), clientRequest.HttpHeaders));
            traceFileWriterMock.Setup(t => t.WriteHeaderFile(It.IsAny <string>(), onPremiseTargetResponse.HttpHeaders));

            sut.Trace(clientRequest, onPremiseTargetResponse, traceConfigurationId);

            traceFileWriterMock.VerifyAll();
            Directory.Exists("tracefiles").Should().BeTrue();

            Directory.Delete("tracefiles");
        }
예제 #14
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());
        }
예제 #15
0
        public void AddContentHeaders_adds_content_headers_to_ClientRequest_headers()
        {
            var clientRequest = new OnPremiseConnectorRequest
            {
                HttpHeaders = new Dictionary <string, string>
                {
                    { "Content-Length", "3" }
                }
            };
            var request = new HttpRequestMessage
            {
                Content = new ByteArrayContent(new byte[] { })
            };
            var sut = new OnPremiseRequestBuilder();

            request.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

            sut.AddContentHeaders(clientRequest, request);

            clientRequest.HttpHeaders.Should().HaveCount(2);
            clientRequest.HttpHeaders.Last().Key.Should().Be("Content-Disposition");
        }
예제 #16
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));
        }
        public async Task <IOnPremiseConnectorRequest> BuildFromHttpRequest(HttpRequestMessage message, Guid originId, string pathWithoutUserName)
        {
            var request = new OnPremiseConnectorRequest()
            {
                RequestId      = Guid.NewGuid().ToString(),
                HttpMethod     = message.Method.Method,
                Url            = pathWithoutUserName + message.RequestUri.Query,
                HttpHeaders    = message.Headers.ToDictionary(kvp => kvp.Key, kvp => CombineMultipleHttpHeaderValuesIntoOneCommaSeparatedValue(kvp.Value), StringComparer.OrdinalIgnoreCase),
                OriginId       = originId,
                RequestStarted = DateTime.UtcNow,
                Expiration     = _configuration.RequestExpiration,
                ContentLength  = message.Content.Headers.ContentLength.GetValueOrDefault(0),
                Stream         = await message.Content.ReadAsStreamAsync().ConfigureAwait(false),
            };

            request.HttpHeaders = message.Headers
                                  .Union(message.Content.Headers)
                                  .Where(kvp => _ignoredHeaders.All(name => name != kvp.Key))
                                  .Select(kvp => new { Name = kvp.Key, Value = CombineMultipleHttpHeaderValuesIntoOneCommaSeparatedValue(kvp.Value) })
                                  .ToDictionary(header => header.Name, header => header.Value);

            return(request);
        }
예제 #18
0
        public async Task <IOnPremiseConnectorRequest> BuildFrom(HttpRequestMessage request, string originId, string pathWithoutUserName)
        {
            var onPremiseConnectorRequest = new OnPremiseConnectorRequest
            {
                RequestId = Guid.NewGuid().ToString(),

                Body = await GetClientRequestBodyAsync(request.Content),

                HttpMethod = request.Method.Method,
                Url        = pathWithoutUserName + request.RequestUri.Query,

                HttpHeaders = request.Headers.ToDictionary(kvp => kvp.Key, kvp => CombineMultipleHttpHeaderValuesIntoOneCommaSeperatedValue(kvp.Value), StringComparer.OrdinalIgnoreCase),

                OriginId = originId,

                RequestStarted = DateTime.UtcNow
            };

            AddContentHeaders(onPremiseConnectorRequest, request);
            RemoveIgnoredHeaders(onPremiseConnectorRequest);

            return(onPremiseConnectorRequest);
        }
예제 #19
0
        public async Task <IOnPremiseConnectorRequest> BuildFromHttpRequest(HttpRequestMessage message, Guid originId, string pathWithoutUserName)
        {
            var request = new OnPremiseConnectorRequest
            {
                RequestId      = Guid.NewGuid().ToString(),
                HttpMethod     = message.Method.Method,
                Url            = pathWithoutUserName + message.RequestUri.Query,
                HttpHeaders    = message.Headers.ToDictionary(kvp => kvp.Key, kvp => CombineMultipleHttpHeaderValuesIntoOneCommaSeperatedValue(kvp.Value), StringComparer.OrdinalIgnoreCase),
                OriginId       = originId,
                RequestStarted = DateTime.UtcNow,
                Expiration     = _configuration.RequestExpiration,
            };

            if (message.Content.Headers.ContentLength.GetValueOrDefault(0x10000) >= 0x10000)
            {
                var contentStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false);

                using (var storeStream = _postDataTemporaryStore.CreateRequestStream(request.RequestId))
                {
                    await contentStream.CopyToAsync(storeStream).ConfigureAwait(false);

                    if (storeStream.Length < 0x10000)
                    {
                        if (storeStream.Length == 0)
                        {
                            // no body available (e.g. GET request)
                        }
                        else
                        {
                            // the body is small enough to be used directly
                            request.Body         = new byte[storeStream.Length];
                            storeStream.Position = 0;
                            await storeStream.ReadAsync(request.Body, 0, (int)storeStream.Length).ConfigureAwait(false);
                        }

                        // TODO delete obsolete file now
                    }
                    else
                    {
                        // a length of 0 indicates that there is a larger body available on the server
                        request.Body = Array.Empty <byte>();
                    }

                    request.ContentLength = storeStream.Length;
                }
            }
            else
            {
                var contentLength = message.Content.Headers.ContentLength.GetValueOrDefault(0);
                if (contentLength > 0)
                {
                    // we have a body, and it is small enough to be transmitted directly
                    var contentStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false);

                    request.Body = new byte[contentLength];
                    await contentStream.ReadAsync(request.Body, 0, (int)contentLength).ConfigureAwait(false);

                    request.ContentLength = contentLength;
                }
            }

            request.HttpHeaders = message.Headers
                                  .Union(message.Content.Headers)
                                  .Where(kvp => _ignoredHeaders.All(name => name != kvp.Key))
                                  .Select(kvp => new { Name = kvp.Key, Value = CombineMultipleHttpHeaderValuesIntoOneCommaSeperatedValue(kvp.Value) })
                                  .ToDictionary(header => header.Name, header => header.Value);

            return(request);
        }