public override BodyDataTransformResult Transform(HttpRequestRecord record, byte[] body, StringValues contentTypeHeaderValues) { var data = MessagePack.LZ4MessagePackSerializer.Deserialize <MyClass>(body, MessagePack.Resolvers.ContractlessStandardResolver.Instance); var json = MessagePack.MessagePackSerializer.ToJson <MyClass>(data, MessagePack.Resolvers.ContractlessStandardResolver.Instance); return(new BodyDataTransformResult(new UTF8Encoding(false).GetBytes(json), contentTypeHeaderValues.ToString(), "application/json")); }
public bool TryTransform(HttpRequestRecord record, ReadOnlySpan <byte> body, StringValues contentTypeHeaderValues, out BodyDataTransformResult result) { var json = MessagePackSerializer.ConvertToJson(body.ToArray(), MessagePack.Resolvers.ContractlessStandardResolver.Options); result = new BodyDataTransformResult(Encoding.UTF8.GetBytes(json), contentTypeHeaderValues.ToString(), "application/json"); return(true); }
public async Task UpdateAsync(HttpRequestRecord entry) { await Task.WhenAll( _redis.StringSetAsync(GetRedisKey($"RecordEntry?{entry.Id}"), Serialize(entry)), _redis.StringSetAsync(GetRedisKey($"RecordEntryInfo?{entry.Id}"), Serialize(HttpRequestRecordInfo.CreateFromRecord(entry))) ); }
public static BodyDataPayload CreateFromRecord(HttpRequestRecord record, IDictionary <string, StringValues>?headers, ReadOnlySpan <byte> body, IBodyDataTransformer transformer) { if (body.IsEmpty) { return(new BodyDataPayload(Convert.ToBase64String(Array.Empty <byte>()), true, "")); } var payloadBody = body; var payloadBodyContentType = string.Empty; var transformedBodyContentType = string.Empty; if (headers != null && headers.TryGetValue("Content-Type", out var contentType)) { if (transformer.TryTransform(record, body, contentType, out var result)) { payloadBodyContentType = result.TransformedContentType; transformedBodyContentType = result.TransformedContentType; payloadBody = result.Body; } } if (payloadBodyContentType.StartsWith("text/") || payloadBodyContentType.StartsWith("application/json") || payloadBodyContentType.StartsWith("application/x-www-form-urlencoded")) { return(new BodyDataPayload(Encoding.UTF8.GetString(payloadBody), false, transformedBodyContentType)); } else { return(new BodyDataPayload(Convert.ToBase64String(payloadBody), true, transformedBodyContentType)); } }
private async Task PostprocessAsync(HttpContext context, RinOptions options, HttpRequestRecord record) { var request = context.Request; var response = context.Response; record.Processing.Complete(); record.ResponseStatusCode = response.StatusCode; record.ResponseHeaders = response.Headers.ToDictionary(k => k.Key, v => v.Value); if (options.RequestRecorder.EnableBodyCapturing) { var memoryStreamRequestBody = new MemoryStream(); request.Body.Position = 0; // rewind the stream to head await request.Body.CopyToAsync(memoryStreamRequestBody); var feature = context.Features.Get <IRinRequestRecordingFeature>(); await _eventBusStoreBody.PostAsync(new StoreBodyEventMessage(StoreBodyEvent.Request, record.Id, memoryStreamRequestBody.ToArray())); await _eventBusStoreBody.PostAsync(new StoreBodyEventMessage(StoreBodyEvent.Response, record.Id, feature.ResponseDataStream.GetCapturedData())); } var exceptionFeature = context.Features.Get <IExceptionHandlerFeature>(); if (exceptionFeature != null) { record.Exception = new ExceptionData(exceptionFeature.Error); } }
private void FiddlerBeforeResponse(Session session) { Uri uri = new Uri(session.fullUrl); if (FileExtensionsToExclude.Count > 0 && FileExtensionsToExclude.Any(x => string.Equals(x, Path.GetExtension(uri.AbsolutePath), StringComparison.OrdinalIgnoreCase))) { return; } if (HostNamesToCollect.Count > 0 && !HostNamesToCollect.Any(x => string.Equals(x, GetHostAndPort(uri), StringComparison.OrdinalIgnoreCase))) { return; } if (RegexToExcludeUrls.Count > 0 && RegexToExcludeUrls.Any(x => Regex.IsMatch(uri.ToString(), x, RegexOptions.IgnoreCase))) { return; } NameValueCollection queryData = HttpUtility.ParseQueryString(uri.Query); string method = session.oRequest.headers.HTTPMethod; if (HttpMethodsToCollect.Count > 0 && !HttpMethodsToCollect.Any(x => string.Equals(x, method, StringComparison.OrdinalIgnoreCase))) { return; } NameValueCollection requestHeaders = new NameValueCollection(); foreach (HTTPHeaderItem httpRequestHeader in session.oRequest.headers) { requestHeaders.Add(httpRequestHeader.Name, httpRequestHeader.Value); } string requestContent = (session.RequestBody != null) && (session.RequestBody.Length > 0) ? CONFIG.oHeaderEncoding.GetString(session.RequestBody) : null; string requestContentType = requestHeaders["Content-Type"] ?? string.Empty; NameValueCollection postData = !string.Equals(method, "POST", StringComparison.OrdinalIgnoreCase) || requestContentType == "application/json" || string.IsNullOrWhiteSpace(requestContent) ? null : GetRequestPostAsDictionary(requestContent); int responseStatus = session.responseCode; NameValueCollection responseHeaders = new NameValueCollection(); foreach (HTTPHeaderItem httpResponseHeader in session.oResponse.headers) { responseHeaders.Add(httpResponseHeader.Name, httpResponseHeader.Value); } string responseContent = (session.ResponseBody != null && session.ResponseBody.Length > 0) ? CONFIG.oHeaderEncoding.GetString(session.ResponseBody) : null; HttpRequestRecord httpRequestRecord = new HttpRequestRecord(uri, queryData, method, requestHeaders, requestContent, requestContentType, postData, responseStatus, responseHeaders, responseContent); m_HttpRequestRecordCollection.Add(httpRequestRecord); HttpRequestRecordReceived(this, httpRequestRecord); }
public BodyDataTransformResult Transform(HttpRequestRecord record, byte[] body, StringValues contentTypeHeaderValues) { var transformer = _transformers.FirstOrDefault(x => x.CanTransform(record, contentTypeHeaderValues)); if (transformer != null) { return(transformer.Transform(record, body, contentTypeHeaderValues)); } return(new BodyDataTransformResult(body, contentTypeHeaderValues.ToString(), null)); }
public bool TryTransform(HttpRequestRecord record, ReadOnlySpan <byte> body, StringValues contentTypeHeaderValues, out BodyDataTransformResult result) { var transformer = _transformers.FirstOrDefault(x => x.CanTransform(record, contentTypeHeaderValues)); if (transformer != null) { return(transformer.TryTransform(record, body, contentTypeHeaderValues, out result)); } result = default; return(false); }
public bool CanTransform(HttpRequestRecord record, StringValues contentTypeHeaderValues) { // NOTE: Currently, this transformer can handle only Unary request. var methodHandler = _serviceDefinition.MethodHandlers.FirstOrDefault(x => string.Concat("/" + x.ServiceName, "/", x.MethodName) == record.Path); if (methodHandler == null || methodHandler.MethodType != MethodType.Unary) { return(false); } return(contentTypeHeaderValues.Any(x => x == "application/grpc")); }
public async Task AddAsync(HttpRequestRecord entry) { await Task.WhenAll( _redis.ListLeftPushAsync(GetRedisKey($"Records"), entry.Id), _redis.StringSetAsync(GetRedisKey($"RecordEntry?{entry.Id}"), Serialize(entry), _options.Expiry), _redis.StringSetAsync(GetRedisKey($"RecordEntryInfo?{entry.Id}"), Serialize(HttpRequestRecordInfo.CreateFromRecord(entry)), _options.Expiry) ); await Task.WhenAll( _redis.ListTrimAsync(GetRedisKey($"Records"), 0, _rinOptions.RequestRecorder.RetentionMaxRequests), _redis.KeyExpireAsync(GetRedisKey($"Records"), _options.Expiry) ); }
private void AddRecordToListBox(HttpRequestRecord record) { MethodInvoker addListBoxItem = () => listBoxRecord.Items.Add(string.Format("{0}{1} : {2}", record.Method, (record.ResponseStatus > 0) ? string.Format("({0} {1})", record.ResponseStatus, Enum.GetName(typeof(System.Net.HttpStatusCode), record.ResponseStatus)) : null, record.Uri.AbsoluteUri)); if (listBoxRecord.InvokeRequired) { listBoxRecord.Invoke(new MethodInvoker(addListBoxItem)); } else { addListBoxItem(); } }
public async Task InvokeAsync(HttpContext context, RinOptions options) { var request = context.Request; var response = context.Response; if (request.Path.StartsWithSegments(options.Inspector.MountPath) || (options.RequestRecorder.Excludes.Any(x => x.Invoke(request)))) { await _next(context); return; } var timelineRoot = TimelineScope.Prepare(); HttpRequestRecord record = default; try { record = await PreprocessAsync(context, options, timelineRoot); } catch (Exception ex) { _logger.LogError(ex, "Unhandled Exception was thrown until pre-processing"); } try { await _next(context); } catch (Exception ex) { if (record != null) { record.Exception = new ExceptionData(ex); } throw; } finally { try { await PostprocessAsync(context, options, record); } catch (Exception ex) { _logger.LogError(ex, "Unhandled Exception was thrown until post-processing"); } } }
public Task UpdateAsync(HttpRequestRecord record) { _lock.EnterWriteLock(); try { if (_entries.TryGetValue(record.Id, out var entry)) { entry.Record = record; } } finally { _lock.ExitWriteLock(); } return(Task.CompletedTask); }
private void btnLoadCollectedData_Click(object sender, EventArgs e) { if (ofdCollectedData.ShowDialog() == DialogResult.OK) { HttpRequestRecordCollection httpRequestRecordCollection = m_HttpRequestRecordManager.Load(ofdCollectedData.FileName); m_FiddlerHttpRequestRecordCollector.SetCollectedRecords(httpRequestRecordCollection); listBoxRecord.Items.Clear(); for (int i = 0; i < httpRequestRecordCollection.Count; i++) { HttpRequestRecord httpRequestRecord = httpRequestRecordCollection[i]; AddRecordToListBox(httpRequestRecord); } } }
private async Task <HttpRequestRecord> PreprocessAsync(HttpContext context, RinOptions options, ITimelineScope timelineRoot) { var request = context.Request; var response = context.Response; var record = new HttpRequestRecord() { Id = Guid.NewGuid().ToString(), IsHttps = request.IsHttps, Host = request.Host.Value, QueryString = request.QueryString.Value, Path = request.Path, Method = request.Method, RequestReceivedAt = DateTimeOffset.Now, RequestHeaders = request.Headers.ToDictionary(k => k.Key, v => v.Value), RemoteIpAddress = request.HttpContext.Connection.RemoteIpAddress, Timeline = timelineRoot, }; // Set Rin recorder feature. var feature = new RinRequestRecordingFeature(record);; _recordingFeatureAccessor.SetValue(feature); context.Features.Set <IRinRequestRecordingFeature>(feature); await _eventBus.PostAsync(new RequestEventMessage(EventSourceName, record, RequestEvent.BeginRequest)); // Set a current Rin request ID to response header. context.Response.Headers.Add("X-Rin-Request-Id", record.Id); if (options.RequestRecorder.EnableBodyCapturing) { context.EnableResponseDataCapturing(); request.EnableBuffering(); } response.OnStarting(OnStarting, record); response.OnCompleted(OnCompleted, record); // Execute pipeline middlewares. record.Processing = TimelineScope.Create("Processing", TimelineEventCategory.AspNetCoreCommon); return(record); }
private List <HttpRequestWorker> CreateHttpRequestWorkers(int maxSleepTime, Random random, int minSleepTime) { List <HttpRequestWorker> httpRequestWorkers = new List <HttpRequestWorker>(m_HttpRequestRecords.Count); for (int i = 0; i < m_HttpRequestRecords.Count; i++) { HttpRequestRecord httpRequestRecord = m_HttpRequestRecords[i]; HttpRequestWorker httpRequestWorker = new HttpRequestWorker( httpRequestRecord, maxSleepTime == 0 ? random.Next(0, minSleepTime) : random.Next(minSleepTime, maxSleepTime), 50); httpRequestWorker.HttpRequestProcessed += (worker, result) => { MethodInvoker addListViewItem = () => { ListViewItem item = new ListViewItem(result.HttpRequestRecord.Uri.ToString()); item.SubItems.Add(result.Success ? "Success" : "Fail"); item.SubItems.Add(GetHttpStatusText(result.HttpResponseStatusCode)); item.SubItems.Add(result.ElapsedMilliseconds.ToString(CultureInfo.InvariantCulture)); lvRequests.Items.Add(item); }; if (result.Success) { Interlocked.Increment(ref m_SuccessfulRequestCount); } if (lvRequests.InvokeRequired) { lvRequests.Invoke(new MethodInvoker(addListViewItem)); } else { addListViewItem(); } }; httpRequestWorkers.Add(httpRequestWorker); } return(httpRequestWorkers); }
public static BodyDataPayload CreateFromRecord(HttpRequestRecord record, IDictionary <string, StringValues> headers, byte[] body, IBodyDataTransformer transformer) { if (headers.TryGetValue("Content-Type", out var contentType)) { var result = transformer.Transform(record, body, contentType); if (result.ContentType.StartsWith("text/") || result.ContentType.StartsWith("application/json") || result.ContentType.StartsWith("text/json") || result.ContentType.StartsWith("application/x-www-form-urlencoded")) { return(new BodyDataPayload(new UTF8Encoding(false).GetString(result.Body), false, result.TransformedContentType ?? "")); } else { return(new BodyDataPayload(Convert.ToBase64String(result.Body), true, result.TransformedContentType ?? "")); } } return(new BodyDataPayload(Convert.ToBase64String(body), true, "")); }
public RequestRecordDetailPayload(HttpRequestRecord record) { Id = record.Id; ParentId = record.ParentId; IsCompleted = record.IsCompleted; IsHttps = record.IsHttps; Host = record.Host.Value; Method = record.Method; Path = record.Path; QueryString = record.QueryString.Value; ResponseStatusCode = record.ResponseStatusCode; RemoteIpAddress = record.RemoteIpAddress.ToString(); RequestHeaders = record.RequestHeaders; ResponseHeaders = record.ResponseHeaders; RequestReceivedAt = record.RequestReceivedAt; TransferringCompletedAt = record.TransferringCompletedAt; Exception = record.Exception; Timeline = new TimelineData(record.Timeline); }
public bool TryTransform(HttpRequestRecord record, ReadOnlySpan <byte> body, StringValues contentTypeHeaderValues, out BodyDataTransformResult result) { var methodHandler = _serviceDefinition.MethodHandlers.FirstOrDefault(x => string.Concat("/" + x.ServiceName, "/", x.MethodName) == record.Path); if (methodHandler == null) { result = default; return(false); } try { var deserialized = MessagePackSerializer.Deserialize(methodHandler.UnwrappedResponseType, body.Slice(5).ToArray() /* Skip gRPC Compressed Flag + Message length */, _serializerOptions); result = new BodyDataTransformResult(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(deserialized, RinMagicOnionSupportJsonSerializerOptions.Default)), "application/grpc", "application/json"); return(true); } catch { result = default; return(false); } }
public Task AddAsync(HttpRequestRecord record) { _lock.EnterWriteLock(); try { _entries[record.Id] = new RecordEntry { Record = record }; _entryIds.Enqueue(record.Id); if (_entryIds.Count > _retentionMaxRequests) { var deletedKey = _entryIds.Dequeue(); _entries.Remove(deletedKey); } } finally { _lock.ExitWriteLock(); } return(Task.CompletedTask); }
public RinRequestRecordingFeature(HttpRequestRecord record) { Record = record; }
public abstract BodyDataTransformResult Transform(HttpRequestRecord record, byte[] body, StringValues contentTypeHeaderValues);
public bool CanTransform(HttpRequestRecord record, StringValues contentTypeHeaderValues) { return(true); }
public RequestEventMessage(string eventSource, HttpRequestRecord value, RequestEvent requestEvent) { EventSource = eventSource; Value = value; Event = requestEvent; }
public bool CanTransform(HttpRequestRecord record, StringValues contentTypeHeaderValues) { return(contentTypeHeaderValues.Any(x => x == "application/x-msgpack")); }
public abstract bool CanTransform(HttpRequestRecord record, StringValues contentTypeHeaderValues);
private void FiddlerHttpRequestRecordCollectorHttpRequestRecordReceived(FiddlerHttpRequestRecordCollector collector, HttpRequestRecord record) { AddRecordToListBox(record); }