Skip to content

Commit 8c05f60

Browse files
authored
Merge pull request #470 from MicrosoftEdge/api-webresourceresponsereceived-draft
Create WebResourceResponseReceived.md
2 parents 6d95286 + 0fa9c02 commit 8c05f60

1 file changed

Lines changed: 232 additions & 0 deletions

File tree

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
# Background
2+
The WebView2 team has been asked for an API to get the response for a web
3+
resource as it was received and to provide request headers not available when
4+
`WebResourceRequested` event is raised (such as HTTP Authentication headers).
5+
The `WebResourceResponseReceived` event provides such response representation
6+
and exposes the request as committed.
7+
8+
In this document we describe the new API. We'd appreciate your feedback.
9+
10+
# Description
11+
The `WebResourceResponseReceived` event allows developers to inspect the
12+
response object from URL requests (such as HTTP/HTTPS, file and data). A key
13+
scenario is to allow developers to get Auth headers from an HTTP response to
14+
authenticate other tools they're using, since the Auth headers are not exposed
15+
in the `WebResourceRequested` event.
16+
17+
This event is raised when the WebView receives the response for a request for a
18+
web resource. It provides access to both the response as it was received and the
19+
request as it was committed, including modifications made by the network stack
20+
(such as the adding of HTTP Authorization headers). The app can use this event
21+
to view the actual request and response for a web resource, but modifications
22+
made to these objects are ignored.
23+
24+
When the event is raised, the WebView will pass a
25+
`WebResourceResponseReceivedEventArgs`, which lets the app view the request and
26+
response. The additional `PopulateResponseContent` API is exposed from the event
27+
arguments so the app can get the response's body (if it has one). If the app
28+
tries to get the response content before the first call to
29+
`PopulateResponseContent` completes, the stream object returned will be null.
30+
31+
# Examples
32+
The following code snippets demonstrate how the `WebResourceResponseReceived`
33+
event can be used:
34+
35+
## COM
36+
```cpp
37+
EventRegistrationToken m_webResourceResponseReceivedToken = {};
38+
39+
m_webview->add_WebResourceResponseReceived(
40+
Callback<ICoreWebView2WebResourceResponseReceivedEventHandler>(
41+
[this](ICoreWebView2* webview, ICoreWebView2WebResourceResponseReceivedEventArgs* args)
42+
-> HRESULT {
43+
// The request object as committed
44+
wil::com_ptr<ICoreWebView2WebResourceRequest> webResourceRequest;
45+
CHECK_FAILURE(args->get_Request(&webResourceRequest));
46+
// The response object as received
47+
wil::com_ptr<ICoreWebView2WebResourceResponse> webResourceResponse;
48+
CHECK_FAILURE(args->get_Response(&webResourceResponse));
49+
50+
// Get body content for the response. Redirect responses will
51+
// return an error HRESULT as their body (if any) is ignored.
52+
HRESULT populateCallResult = args->PopulateResponseContent(
53+
Callback<
54+
ICoreWebView2WebResourceResponseReceivedEventArgsPopulateResponseContentCompletedHandler>(
55+
[this, webResourceRequest, webResourceResponse](HRESULT result) {
56+
// The response might not have a body.
57+
bool populatedBody = SUCCEEDED(result);
58+
59+
std::wstring message =
60+
L"{ \"kind\": \"event\", \"name\": "
61+
L"\"WebResourceResponseReceived\", \"args\": {"
62+
L"\"request\": " +
63+
RequestToJsonString(webResourceRequest.get()) +
64+
L", "
65+
L"\"response\": " +
66+
ResponseToJsonString(webResourceResponse.get()) + L"}";
67+
68+
message +=
69+
WebViewPropertiesToJsonString(m_webview.get());
70+
message += L"}";
71+
PostEventMessage(message);
72+
return S_OK;
73+
})
74+
.Get());
75+
76+
return S_OK;
77+
})
78+
.Get(),
79+
&m_webResourceResponseReceivedToken);
80+
```
81+
82+
## C#
83+
```c#
84+
WebView.WebResourceResponseReceived += WebView_WebResourceResponseReceived;
85+
86+
// Note: modifications made to request and response are ignored
87+
private async void WebView_WebResourceResponseReceived(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e)
88+
{
89+
// Actual headers sent with request
90+
foreach (var current in e.Request.Headers)
91+
Console.WriteLine(current);
92+
93+
// Headers in response received
94+
foreach (var current in e.Response.Headers)
95+
Console.WriteLine(current);
96+
97+
// Status code from response received
98+
int status = e.Response.StatusCode;
99+
if (status == 200)
100+
{
101+
// Handle
102+
Console.WriteLine("Request succeeded!");
103+
104+
// Get response body
105+
try
106+
{
107+
await e.PopulateResponseContentAsync();
108+
DoSomethingWithResponseBody(e.Response.Content);
109+
}
110+
catch (COMException ex)
111+
{
112+
// A COMException will be thrown if the request has no body.
113+
}
114+
}
115+
}
116+
```
117+
118+
119+
# Remarks
120+
Calling `PopulateResponseContent` will fail/throw a COMException if the response
121+
has no body. Note the body for redirect responses is ignored.
122+
123+
124+
# API Notes
125+
See [API Details](#api-details) section below for API reference.
126+
127+
128+
# API Details
129+
## COM
130+
```cpp
131+
library WebView2
132+
{
133+
interface ICoreWebView2 : IUnknown
134+
{
135+
// ...
136+
137+
/// Add an event handler for the WebResourceResponseReceived event.
138+
/// WebResourceResponseReceived event is raised after the WebView has received
139+
/// and processed the response for a WebResource request. The event args
140+
/// include the WebResourceRequest as committed and the WebResourceResponse
141+
/// received, including any additional headers added by the network stack that
142+
/// were not be included as part of the associated WebResourceRequested event,
143+
/// such as Authentication headers.
144+
HRESULT add_WebResourceResponseReceived(
145+
[in] ICoreWebView2WebResourceResponseReceivedEventHandler* eventHandler,
146+
[out] EventRegistrationToken* token);
147+
/// Removes the WebResourceResponseReceived event handler previously added
148+
/// with add_WebResourceResponseReceived
149+
HRESULT remove_WebResourceResponseReceived(
150+
[in] EventRegistrationToken token);
151+
}
152+
153+
/// Raised when a response for a request is received for a Web resource in the webview.
154+
/// Host can use this event to view the actual request and response for a Web resource.
155+
/// This includes any request or response modifications made by the network stack (such as
156+
/// the adding of Authorization headers) after the WebResourceRequested event for
157+
/// the associated request has been raised. Modifications made to the request or
158+
/// response objects are ignored.
159+
interface ICoreWebView2WebResourceResponseReceivedEventHandler : IUnknown
160+
{
161+
/// Called to provide the implementer with the event args for the
162+
/// corresponding event.
163+
HRESULT Invoke(
164+
[in] ICoreWebView2* sender,
165+
[in] ICoreWebView2WebResourceResponseReceivedEventArgs* args);
166+
}
167+
168+
/// Completion handler for PopulateResponseContent async method. It's invoked
169+
/// when the Content stream of the Response of a WebResourceResponseReceieved
170+
/// event is available.
171+
interface ICoreWebView2WebResourceResponseReceivedEventArgsPopulateResponseContentCompletedHandler : IUnknown
172+
{
173+
/// Called to provide the implementer with the completion status
174+
/// of the corresponding asynchronous method call.
175+
HRESULT Invoke([in] HRESULT errorCode);
176+
}
177+
178+
/// Event args for the WebResourceResponseReceived event. Will contain the
179+
/// request as it was sent and the response as it was received.
180+
/// Note: To get the response content stream, first call PopulateResponseContent
181+
/// and wait for the async call to complete, otherwise the content stream object
182+
/// returned will be null.
183+
interface ICoreWebView2WebResourceResponseReceivedEventArgs : IUnknown
184+
{
185+
/// Web resource request object. Any modifications to this object will be ignored.
186+
[propget] HRESULT Request([out, retval] ICoreWebView2WebResourceRequest** request);
187+
/// Web resource response object. Any modifications to this object
188+
/// will be ignored.
189+
[propget] HRESULT Response([out, retval] ICoreWebView2WebResourceResponse** response);
190+
191+
/// Async method to ensure that the Content property of the response contains the actual response body content.
192+
/// If this method is being called again before a first call has completed, all handlers are invoked at the same time.
193+
/// If this method is being called after a first call has completed, the handler is invoked immediately.
194+
HRESULT PopulateResponseContent(ICoreWebView2WebResourceResponseReceivedEventArgsPopulateResponseContentCompletedHandler* handler);
195+
}
196+
}
197+
```
198+
199+
## WinRT
200+
```c#
201+
namespace Microsoft.Web.WebView2.Core
202+
{
203+
runtimeclass CoreWebView2
204+
{
205+
// ...
206+
207+
/// WebResourceResponseReceived event is raised after the WebView has received and processed the response for a WebResource request.
208+
/// The event args include the WebResourceRequest as committed and the WebResourceResponse received,
209+
/// including any additional headers added by the network stack that were not be included as part of
210+
/// the associated WebResourceRequested event, such as Authentication headers.
211+
event Windows.Foundation.TypedEventHandler<CoreWebView2, CoreWebView2WebResourceResponseReceivedEventArgs> WebResourceResponseReceived;
212+
}
213+
214+
/// Event args for the WebResourceResponseReceived event.
215+
/// Note: To get the response content stream, first call PopulateResponseContentAsync and
216+
/// wait for the call to complete, otherwise the content stream object returned will be null.
217+
runtimeclass CoreWebView2WebResourceResponseReceivedEventArgs
218+
{
219+
/// Web resource request object.
220+
/// Any modifications to this object will be ignored.
221+
CoreWebView2WebResourceRequest Request { get; };
222+
/// Web resource response object.
223+
/// Any modifications to this object will be ignored.
224+
CoreWebView2WebResourceResponse Response { get; };
225+
226+
/// Async method to ensure that the Content property of the response contains the actual response body content.
227+
/// If this method is being called again before a first call has completed, it will complete at the same time all prior calls do.
228+
/// If this method is being called after a first call has completed, it will return immediately (asynchronously).
229+
Windows.Foundation.IAsyncAction PopulateResponseContentAsync();
230+
}
231+
}
232+
```

0 commit comments

Comments
 (0)