public async Task TestPlaybackSetsRetryAfterToZero() { RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); var httpContext = new DefaultHttpContext(); httpContext.Request.Headers["x-recording-file"] = "Test.RecordEntries/response_with_retry_after.json"; var controller = new Playback(testRecordingHandler) { ControllerContext = new ControllerContext() { HttpContext = httpContext } }; await controller.Start(); var recordingId = httpContext.Response.Headers["x-recording-id"].ToString(); Assert.NotNull(recordingId); Assert.True(testRecordingHandler.PlaybackSessions.ContainsKey(recordingId)); var entry = testRecordingHandler.PlaybackSessions[recordingId].Session.Entries[0]; HttpRequest request = TestHelpers.CreateRequestFromEntry(entry); HttpResponse response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); Assert.Equal("0", response.Headers["Retry-After"]); // this response did not have the retry-after header initially, so it should not have been added. entry = testRecordingHandler.PlaybackSessions[recordingId].Session.Entries[0]; request = TestHelpers.CreateRequestFromEntry(entry); response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); Assert.False(response.Headers.ContainsKey("Retry-After")); }
public async Task CanApplyHeaderTransformWithCondition() { var headerTransform = new HeaderTransform( "Location", "http://localhost", condition: new ApplyCondition { ResponseHeader = new HeaderCondition { Key = "Location", ValueRegex = @".*/Tables\(.*" } }); RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); testRecordingHandler.Transforms.Clear(); testRecordingHandler.Transforms.Add(headerTransform); var playbackContext = new DefaultHttpContext(); var targetFile = "Test.RecordEntries/response_with_header_to_transform.json"; var transformedEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[0]; var untransformedEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[1]; // start playback var body = "{\"x-recording-file\":\"" + targetFile + "\"}"; playbackContext.Request.Body = TestHelpers.GenerateStreamRequestBody(body); playbackContext.Request.ContentLength = body.Length; var controller = new Playback(testRecordingHandler) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // transform should apply only to first request HttpRequest request = TestHelpers.CreateRequestFromEntry(transformedEntry); HttpResponse response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); Assert.Equal("http://localhost", response.Headers["Location"]); // this one should keep the original Location value request = TestHelpers.CreateRequestFromEntry(untransformedEntry); response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); var originalLocation = untransformedEntry.Response.Headers["Location"]; Assert.Equal(originalLocation, response.Headers["Location"]); }
public async Task ConditionalTransformAppliesForRegex() { var clientIdTransform = new StorageRequestIdTransform(condition: new ApplyCondition() { UriRegex = @".+/Tables.*" }); RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); testRecordingHandler.Transforms.Clear(); testRecordingHandler.Transforms.Add(clientIdTransform); var playbackContext = new DefaultHttpContext(); var targetHeaderKey = "x-ms-client-request-id"; var targetFile = "Test.RecordEntries/response_with_xml_body.json"; var transformedEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[0]; var clientId = transformedEntry.Request.Headers[targetHeaderKey][0]; var untransformedEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[1]; // start playback var body = "{\"x-recording-file\":\"" + targetFile + "\"}"; playbackContext.Request.Body = TestHelpers.GenerateStreamRequestBody(body); playbackContext.Request.ContentLength = body.Length; var controller = new Playback(testRecordingHandler) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // transform should apply only to first/last request HttpRequest transformedRequest = TestHelpers.CreateRequestFromEntry(transformedEntry); HttpResponse transformedResponse = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, transformedRequest, transformedResponse); Assert.Contains(clientId, transformedResponse.Headers["x-ms-client-request-id"].ToString()); // this one should not add the x-ms-client-request-id to the response, the transform should NOT apply HttpRequest nonTransformedRequest = TestHelpers.CreateRequestFromEntry(untransformedEntry); HttpResponse nonTransformedresponse = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, nonTransformedRequest, nonTransformedresponse); Assert.False(nonTransformedresponse.Headers.ContainsKey(targetHeaderKey)); }
public async Task CanApplyHeaderTransform() { var headerTransform = new HeaderTransform( "someNewHeader", "value"); RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); testRecordingHandler.Transforms.Clear(); testRecordingHandler.Transforms.Add(headerTransform); var playbackContext = new DefaultHttpContext(); var targetFile = "Test.RecordEntries/response_with_header_to_transform.json"; var transformedEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[0]; // start playback playbackContext.Request.Headers["x-recording-file"] = targetFile; var controller = new Playback(testRecordingHandler) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // transform should apply HttpRequest request = TestHelpers.CreateRequestFromEntry(transformedEntry); HttpResponse response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); Assert.Equal("value", response.Headers["someNewHeader"]); }
public async Task TestPlaybackThrowsOnDifferentUriOrder() { RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); var playbackContext = new DefaultHttpContext(); var targetFile = "Test.RecordEntries/request_with_subscriptionid.json"; playbackContext.Request.Headers["x-recording-file"] = targetFile; var body = "{\"x-recording-file\":\"" + targetFile + "\"}"; playbackContext.Request.Body = TestHelpers.GenerateStreamRequestBody(body); playbackContext.Request.ContentLength = body.Length; var controller = new Playback(testRecordingHandler, new NullLoggerFactory()) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // prepare recording context playbackContext.Request.Headers.Clear(); playbackContext.Response.Headers.Clear(); var requestHeaders = new Dictionary <string, string>() { { ":authority", "localhost:5001" }, { ":method", "POST" }, { ":path", "/" }, { ":scheme", "https" }, { "Accept-Encoding", "gzip" }, { "Content-Length", "0" }, { "User-Agent", "Go-http-client/2.0" }, { "x-recording-id", recordingId }, { "x-recording-upstream-base-uri", "https://management.azure.com/" } }; foreach (var kvp in requestHeaders) { playbackContext.Request.Headers.Add(kvp.Key, kvp.Value); } playbackContext.Request.Method = "POST"; // the query parameters are in reversed order from the recording deliberately. var queryString = "?uselessUriAddition=hellothere&api-version=2019-05-01"; var path = "/subscriptions/12345678-1234-1234-5678-123456789010/providers/Microsoft.ContainerRegistry/checkNameAvailability"; playbackContext.Request.Host = new HostString("https://localhost:5001"); playbackContext.Features.Get <IHttpRequestFeature>().RawTarget = path + queryString; var resultingException = await Assert.ThrowsAsync <TestRecordingMismatchException>( async() => await testRecordingHandler.HandlePlaybackRequest(recordingId, playbackContext.Request, playbackContext.Response) ); Assert.Contains("Uri doesn't match:", resultingException.Message); }
public async Task CustomMatcherMatchesDifferentUriOrder() { RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); testRecordingHandler.Matcher = new CustomDefaultMatcher(ignoreQueryOrdering: true); var playbackContext = new DefaultHttpContext(); var targetFile = "Test.RecordEntries/request_with_subscriptionid.json"; var body = "{\"x-recording-file\":\"" + targetFile + "\"}"; playbackContext.Request.Body = TestHelpers.GenerateStreamRequestBody(body); playbackContext.Request.ContentLength = body.Length; var controller = new Playback(testRecordingHandler) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // prepare recording context playbackContext.Request.Headers.Clear(); playbackContext.Response.Headers.Clear(); var requestHeaders = new Dictionary <string, string>() { { ":authority", "localhost:5001" }, { ":method", "POST" }, { ":path", "/" }, { ":scheme", "https" }, { "Accept-Encoding", "gzip" }, { "Content-Length", "0" }, { "User-Agent", "Go-http-client/2.0" }, { "x-recording-id", recordingId }, { "x-recording-upstream-base-uri", "https://management.azure.com/" } }; foreach (var kvp in requestHeaders) { playbackContext.Request.Headers.Add(kvp.Key, kvp.Value); } playbackContext.Request.Method = "POST"; // the query parameters are in reversed order from the recording deliberately. var queryString = "?uselessUriAddition=hellothere&api-version=2019-05-01"; var path = "/subscriptions/12345678-1234-1234-5678-123456789010/providers/Microsoft.ContainerRegistry/checkNameAvailability"; playbackContext.Request.Host = new HostString("https://localhost:5001"); playbackContext.Features.Get <IHttpRequestFeature>().RawTarget = path + queryString; await testRecordingHandler.HandlePlaybackRequest(recordingId, playbackContext.Request, playbackContext.Response); Assert.Equal("WESTUS:20210909T204819Z:f9a33867-6efc-4748-b322-303b2b933466", playbackContext.Response.Headers["x-ms-routing-request-id"].ToString()); }
public async Task ApiTransformPullsFromRequest() { var headerTransform = new StorageRequestIdTransform(); RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory()); testRecordingHandler.Transforms.Clear(); testRecordingHandler.Transforms.Add(headerTransform); var playbackContext = new DefaultHttpContext(); var targetFile = "Test.RecordEntries/response_with_header_to_transform.json"; var requestEntry = TestHelpers.LoadRecordSession(targetFile).Session.Entries[0]; var fakeGuid = "not-a-guid"; requestEntry.Request.Headers["x-ms-client-request-id"] = new string[] { fakeGuid }; // start playback var body = "{\"x-recording-file\":\"" + targetFile + "\"}"; playbackContext.Request.Body = TestHelpers.GenerateStreamRequestBody(body); playbackContext.Request.ContentLength = body.Length; var controller = new Playback(testRecordingHandler, new NullLoggerFactory()) { ControllerContext = new ControllerContext() { HttpContext = playbackContext } }; await controller.Start(); var recordingId = playbackContext.Response.Headers["x-recording-id"].ToString(); // transform should apply HttpRequest request = TestHelpers.CreateRequestFromEntry(requestEntry); HttpResponse response = new DefaultHttpContext().Response; await testRecordingHandler.HandlePlaybackRequest(recordingId, request, response); Assert.Equal(fakeGuid, response.Headers["x-ms-client-request-id"].ToString()); }