/// <summary> /// Fulfills request with given response. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is thrown if request interception is not enabled. /// </summary> /// <param name="response">Response that will fulfill this request</param> /// <returns>Task</returns> public async Task RespondAsync(ResponseData response) { if (Url.StartsWith("data:", StringComparison.Ordinal)) { return; } if (!_allowInterception) { throw new PuppeteerException("Request Interception is not enabled!"); } if (_interceptionHandled) { throw new PuppeteerException("Request is already handled!"); } _interceptionHandled = true; var responseHeaders = new List <Header>(); if (response.Headers != null) { foreach (var keyValuePair in response.Headers) { if (keyValuePair.Value == null) { continue; } if (keyValuePair.Value is ICollection values) { foreach (var val in values) { responseHeaders.Add(new Header { Name = keyValuePair.Key, Value = val.ToString() }); } } else { responseHeaders.Add(new Header { Name = keyValuePair.Key, Value = keyValuePair.Value.ToString() }); } } if (!response.Headers.ContainsKey("content-length") && response.BodyData != null) { responseHeaders.Add(new Header { Name = "content-length", Value = response.BodyData.Length.ToString(CultureInfo.CurrentCulture) }); } } if (response.ContentType != null) { responseHeaders.Add(new Header { Name = "content-type", Value = response.ContentType }); } try { await _client.SendAsync("Fetch.fulfillRequest", new FetchFulfillRequest { RequestId = InterceptionId, ResponseCode = response.Status != null ? (int)response.Status : 200, ResponseHeaders = responseHeaders.ToArray(), Body = response.BodyData != null ? Convert.ToBase64String(response.BodyData) : null }).ConfigureAwait(false); } catch (PuppeteerException ex) { // In certain cases, protocol will return error if the request was already canceled // or the page was closed. We should tolerate these errors _logger.LogError(ex.ToString()); } }
/// <summary> /// Fulfills request with given response. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is thrown if request interception is not enabled. /// </summary> /// <param name="response">Response that will fulfill this request</param> /// <returns>Task</returns> public async Task RespondAsync(ResponseData response) { if (Url.StartsWith("data:", StringComparison.Ordinal)) { return; } if (!_allowInterception) { throw new PuppeteerException("Request Interception is not enabled!"); } if (_interceptionHandled) { throw new PuppeteerException("Request is already handled!"); } _interceptionHandled = true; var responseHeaders = new Dictionary <string, object>(); if (response.Headers != null) { foreach (var keyValue in response.Headers) { responseHeaders[keyValue.Key] = keyValue.Value; } } if (response.ContentType != null) { responseHeaders["content-type"] = response.ContentType; } if (!responseHeaders.ContainsKey("content-length") && response.BodyData != null) { responseHeaders["content-length"] = response.BodyData.Length; } var statusCode = response.Status ?? HttpStatusCode.OK; var statusText = statusCode.ToString(); var text = new StringBuilder(); text.AppendLine($"HTTP/1.1 {(int)statusCode} {statusText}"); foreach (var header in responseHeaders) { text.AppendLine($"{header.Key}: {header.Value}"); } text.AppendLine(string.Empty); var responseData = Encoding.UTF8.GetBytes(text.ToString()); if (response.BodyData != null) { var concatenatedData = new byte[responseData.Length + response.BodyData.Length]; responseData.CopyTo(concatenatedData, 0); response.BodyData.CopyTo(concatenatedData, responseData.Length); responseData = concatenatedData; } try { await _client.SendAsync("Network.continueInterceptedRequest", new Dictionary <string, object> { { MessageKeys.InterceptionId, InterceptionId }, { MessageKeys.RawResponse, Convert.ToBase64String(responseData) } }).ConfigureAwait(false); } catch (PuppeteerException ex) { // In certain cases, protocol will return error if the request was already canceled // or the page was closed. We should tolerate these errors _logger.LogError(ex.ToString()); } }
public async Task Respond(ResponseData response) { if (Url.StartsWith("data:", StringComparison.Ordinal)) { return; } Contract.Requires(_allowInterception, "Request interception is not enabled!"); Contract.Requires(!_interceptionHandled, "Request is already handled!"); _interceptionHandled = true; //TODO: In puppeteer this is a buffer but as I don't know the real implementation yet //I will consider this a string var responseBody = response.Body; var responseHeaders = new Dictionary <string, object>(); if (response.Headers != null) { foreach (var keyValue in response.Headers) { responseHeaders[keyValue.Key] = keyValue.Value; } } if (response.ContentType != null) { responseHeaders["content-type"] = response.ContentType; } if (!string.IsNullOrEmpty(responseBody) && !responseHeaders.ContainsKey("content-length")) { responseHeaders["content-length"] = responseBody.Length; } var statusCode = response.Status ?? HttpStatusCode.Accepted; var statusText = statusCode.ToString(); var statusLine = $"HTTP / 1.1${(int)statusCode} ${statusText}"; var text = new StringBuilder(statusLine + "\n"); foreach (var header in responseHeaders) { text.AppendLine($"{header.Key}: {header.Value}"); } text.AppendLine(string.Empty); //This is a buffer in puppeteer but I don't know the final implementation here var responseBuffer = text.ToString(); if (!string.IsNullOrEmpty(responseBody)) { responseBuffer += responseBody; } try { await _client.SendAsync("Network.continueInterceptedRequest", new Dictionary <string, object> { { "interceptionId", InterceptionId }, { "rawResponse", responseBuffer } }); } catch (Exception) { // In certain cases, protocol will return error if the request was already canceled // or the page was closed. We should tolerate these errors //TODO: Choose log mechanism } }