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 onPremiseConnectorResponse = new OnPremiseConnectorResponse() { 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, CreateDummyConfiguration(), loggerMock.Object); var exception = new Exception(); traceFileWriterMock.Setup(t => t.WriteContentFileAsync(It.IsAny <string>(), clientRequest.Body)).Throws(exception); loggerMock.Setup(l => l.Warning(exception, It.IsAny <string>())); sut.Trace(clientRequest, onPremiseConnectorResponse, traceConfigurationId); traceFileWriterMock.VerifyAll(); }
public async Task <IHttpActionResult> Forward() { var requestStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false); OnPremiseConnectorResponse response = null; if (Request.Headers.TryGetValues("X-TTRELAY-METADATA", out var headerValues)) { response = JToken.Parse(headerValues.First()).ToObject <OnPremiseConnectorResponse>(); using (var stream = _postDataTemporaryStore.CreateResponseStream(response.RequestId)) { await requestStream.CopyToAsync(stream).ConfigureAwait(false); response.ContentLength = stream.Length; } } else { // this is a legacy on-premise connector (v1) response = await ForwardLegacyResponse(Encoding.UTF8, requestStream).ConfigureAwait(false); } _logger?.Verbose("Received on-premise response. request-id={RequestId}, content-length={ResponseContentLength}", response.RequestId, response.ContentLength); _backendCommunication.SendOnPremiseTargetResponse(response.OriginId, response); return(Ok()); }
public async Task <IHttpActionResult> Forward() { var claimsPrincipal = (ClaimsPrincipal)RequestContext.Principal; var onPremiseId = claimsPrincipal.FindFirst(AuthorizationServerProvider.OnPremiseIdClaimName)?.Value; Request.GetCallCancelled().Register(() => _logger?.Warning("Disconnect during receiving on-premise response detected. link-id={LinkId}", onPremiseId)); var requestStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false); OnPremiseConnectorResponse response = null; if (Request.Headers.TryGetValues("X-TTRELAY-METADATA", out var headerValues)) { response = JToken.Parse(headerValues.First()).ToObject <OnPremiseConnectorResponse>(); using (var stream = _postDataTemporaryStore.CreateResponseStream(response.RequestId)) { await requestStream.CopyToAsync(stream).ConfigureAwait(false); response.ContentLength = stream.Length; } } else { // this is a legacy on-premise connector (v1) response = await ForwardLegacyResponse(Encoding.UTF8, requestStream).ConfigureAwait(false); } _logger?.Verbose("Received on-premise response. request-id={RequestId}, content-length={ResponseContentLength}", response.RequestId, response.ContentLength); _backendCommunication.SendOnPremiseTargetResponse(response.OriginId, response); return(Ok()); }
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); }
public void GetResponseContentForOnPremiseTargetResponse_does_not_disclose_content_when_other_error_occurred_and_ForwardOnPremiseTargetErrorResponse_is_turned_off() { var sut = new HttpResponseMessageBuilder(null); var onPremiseTargetResponse = new OnPremiseConnectorResponse { StatusCode = HttpStatusCode.NotImplemented }; using (var result = sut.GetResponseContentForOnPremiseTargetResponse(onPremiseTargetResponse, false)) { result.Should().BeNull(); } }
public void GetResponseContentForOnPremiseTargetResponse_does_not_disclose_content_when_InternalServerError_occurred_and_ForwardOnPremiseTargetErrorResponse_is_turned_off() { var sut = new HttpResponseMessageBuilder(null, GetInMemoryStore()); var onPremiseTargetResponse = new OnPremiseConnectorResponse { StatusCode = HttpStatusCode.InternalServerError }; var link = new Link(); using (var result = sut.GetResponseContentForOnPremiseTargetResponse(onPremiseTargetResponse, link)) { result.Should().BeNull(); } }
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 onPremiseConnectorResponse = new OnPremiseConnectorResponse() { 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, CreateDummyConfiguration(), loggerMock.Object); startTime = DateTime.Now; traceFileWriterMock.Setup(t => t.WriteContentFileAsync(It.IsAny <string>(), clientRequest.Body)).Callback((string f, byte[] c) => clientRequestBodyFileName = f); traceFileWriterMock.Setup(t => t.WriteContentFileAsync(It.IsAny <string>(), onPremiseConnectorResponse.Body)).Callback((string f, byte[] c) => onPremiseTargetResponseBodyFileName = f); traceFileWriterMock.Setup(t => t.WriteHeaderFileAsync(It.IsAny <string>(), clientRequest.HttpHeaders)).Callback((string f, IReadOnlyDictionary <string, string> c) => clientRequestHeadersFileName = f); traceFileWriterMock.Setup(t => t.WriteHeaderFileAsync(It.IsAny <string>(), onPremiseConnectorResponse.HttpHeaders)).Callback((string f, IReadOnlyDictionary <string, string> c) => onPremiseTargetResponseHeadersFileName = f); sut.Trace(clientRequest, onPremiseConnectorResponse, traceConfigurationId); var ticks = new DateTime(Int64.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"); }
public async Task GetResponseContentForOnPremiseTargetResponse_sets_StatusCode_accordingly_and_discloses_content() { var sut = new HttpResponseMessageBuilder(null); var onPremiseTargetResponse = new OnPremiseConnectorResponse { StatusCode = HttpStatusCode.OK, Body = new byte[] { 0, 0, 0, 0 }, ContentLength = 4, }; using (var result = sut.GetResponseContentForOnPremiseTargetResponse(onPremiseTargetResponse, false)) { var body = await result.ReadAsByteArrayAsync(); result.Should().NotBeNull(); body.LongLength.Should().Be(4L); } }
public async Task GetResponseContentForOnPremiseTargetResponse_discloses_content_when_other_error_occurred_and_ForwardOnPremiseTargetErrorResponse_is_turned_on() { var sut = new HttpResponseMessageBuilder(null); var onPremiseTargetResponse = new OnPremiseConnectorResponse { StatusCode = HttpStatusCode.NotImplemented, Body = new byte[] { 0, 0, 0 }, ContentLength = 3, }; using (var result = sut.GetResponseContentForOnPremiseTargetResponse(onPremiseTargetResponse, true)) { var body = await result.ReadAsByteArrayAsync(); result.Should().NotBeNull(); body.LongLength.Should().Be(3L); } }
private void FetchResponseBodyForIntercepting(OnPremiseConnectorResponse response) { if (response.ContentLength == 0) { _logger?.Verbose("Received empty body. request-id={RequestId}", response.RequestId); } else if (response.Body != null) { _logger?.Verbose("Received small legacy body with data. request-id={RequestId}, body-length={ResponseContentLength}", response.RequestId, response.Body.Length); } else { _logger?.Verbose("Received body. request-id={RequestId}, content-length={ResponseContentLength}", response.RequestId, response.ContentLength); response.Stream = _postDataTemporaryStore.GetResponseStream(response.RequestId); } }
public async Task GetResponseContentForOnPremiseTargetResponse_discloses_content_when_InternalServerError_occurred_and_ForwardOnPremiseTargetErrorResponse_is_turned_on() { var sut = new HttpResponseMessageBuilder(null, GetInMemoryStore()); var onPremiseTargetResponse = new OnPremiseConnectorResponse { StatusCode = HttpStatusCode.InternalServerError, Body = new byte[] { 0, 0, 0 }, ContentLength = 3, }; var link = new Link { ForwardOnPremiseTargetErrorResponse = true }; using (var result = sut.GetResponseContentForOnPremiseTargetResponse(onPremiseTargetResponse, link)) { var body = await result.ReadAsByteArrayAsync(); result.Should().NotBeNull(); body.LongLength.Should().Be(3L); } }
public void LogRequest_writes_correctly_composed_log_entry_to_the_RelayRepository_with_OnPremiseTargetResult_set() { 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), ContentLength = 3, }; var onPremiseConnectorResponse = new OnPremiseConnectorResponse { RequestStarted = new DateTime(2014, 1, 3), RequestFinished = new DateTime(2014, 1, 4), ContentLength = 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, onPremiseConnectorResponse, Guid.Parse("4bb4ff98-ba03-49ee-bd83-5a229f63fade"), new Guid("35eff886-2d7c-4265-a6a4-f3f471ab93e8"), "gimme/that/file.html", HttpStatusCode.PaymentRequired); 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(new DateTime(2014, 1, 3)); result.OnPremiseTargetOutDate.Should().Be(new DateTime(2014, 1, 4)); result.ContentBytesIn.Should().Be(3L); result.ContentBytesOut.Should().Be(2L); result.LinkId.Should().Be(Guid.Parse("4bb4ff98-ba03-49ee-bd83-5a229f63fade")); }
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 onPremiseConnectorResponse = new OnPremiseConnectorResponse() { 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, CreateDummyConfiguration(), loggerMock.Object); Directory.CreateDirectory("tracefiles"); Directory.Delete("tracefiles"); traceFileWriterMock.Setup(t => t.WriteContentFileAsync(It.IsAny <string>(), clientRequest.Body)); traceFileWriterMock.Setup(t => t.WriteContentFileAsync(It.IsAny <string>(), onPremiseConnectorResponse.Body)); traceFileWriterMock.Setup(t => t.WriteHeaderFileAsync(It.IsAny <string>(), clientRequest.HttpHeaders)); traceFileWriterMock.Setup(t => t.WriteHeaderFileAsync(It.IsAny <string>(), onPremiseConnectorResponse.HttpHeaders)); sut.Trace(clientRequest, onPremiseConnectorResponse, traceConfigurationId); traceFileWriterMock.VerifyAll(); Directory.Exists("tracefiles").Should().BeTrue(); Directory.Delete("tracefiles"); }