|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license.
|
3 | 3 |
|
4 | 4 | import { synchronizeDomContent } from '../Rendering/DomMerging/DomSync';
|
5 |
| -import { attachProgrammaticEnhancedNavigationHandler, handleClickForNavigationInterception, hasInteractiveRouter, isSamePageWithHash, notifyEnhancedNavigationListners, performScrollToElementOnTheSamePage } from './NavigationUtils'; |
| 5 | +import { attachProgrammaticEnhancedNavigationHandler, handleClickForNavigationInterception, hasInteractiveRouter, isSamePageWithHash, notifyEnhancedNavigationListeners, performScrollToElementOnTheSamePage } from './NavigationUtils'; |
6 | 6 |
|
7 | 7 | /*
|
8 | 8 | In effect, we have two separate client-side navigation mechanisms:
|
@@ -42,7 +42,7 @@ let performingEnhancedPageLoad: boolean;
|
42 | 42 | let currentContentUrl = location.href;
|
43 | 43 |
|
44 | 44 | export interface NavigationEnhancementCallbacks {
|
45 |
| - enhancedNavigationStarted: (method: string) => void; |
| 45 | + enhancedNavigationStarted: (resource: string | URL | Request, options: RequestInit) => void; |
46 | 46 | documentUpdated: () => void;
|
47 | 47 | enhancedNavigationCompleted: () => void;
|
48 | 48 | }
|
@@ -184,29 +184,30 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
|
184 | 184 | currentEnhancedNavigationAbortController?.abort();
|
185 | 185 |
|
186 | 186 | // Notify any interactive runtimes that an enhanced navigation is starting
|
187 |
| - notifyEnhancedNavigationListners(internalDestinationHref, interceptedLink); |
188 |
| - |
189 |
| - // Invoke other enhanced navigation handlers |
190 |
| - const requestMethod = fetchOptions?.method ?? 'get'; |
191 |
| - navigationEnhancementCallbacks.enhancedNavigationStarted(requestMethod); |
| 187 | + notifyEnhancedNavigationListeners(internalDestinationHref, interceptedLink); |
192 | 188 |
|
193 | 189 | // Now request the new page via fetch, and a special header that tells the server we want it to inject
|
194 | 190 | // framing boundaries to distinguish the initial document and each subsequent streaming SSR update.
|
195 | 191 | currentEnhancedNavigationAbortController = new AbortController();
|
196 | 192 | const abortSignal = currentEnhancedNavigationAbortController.signal;
|
197 |
| - const responsePromise = fetch(internalDestinationHref, Object.assign(<RequestInit>{ |
| 193 | + const requestInit = Object.assign(<RequestInit>{ |
198 | 194 | signal: abortSignal,
|
199 | 195 | mode: 'no-cors', // If there's a redirection to an external origin, even if it enables CORS, we don't want to receive its content and patch it into our DOM on this origin
|
200 | 196 | headers: {
|
201 | 197 | // Because of no-cors, we can only send CORS-safelisted headers, so communicate the info about
|
202 | 198 | // enhanced nav as a MIME type parameter
|
203 | 199 | 'accept': acceptHeader,
|
204 | 200 | },
|
205 |
| - }, fetchOptions)); |
| 201 | + }, fetchOptions); |
| 202 | + const responsePromise = fetch(internalDestinationHref, requestInit); |
| 203 | + |
| 204 | + // Notify handlers that enhanced navigation has started |
| 205 | + navigationEnhancementCallbacks.enhancedNavigationStarted(internalDestinationHref, requestInit); |
| 206 | + |
206 | 207 | let isNonRedirectedPostToADifferentUrlMessage: string | null = null;
|
207 | 208 | await getResponsePartsWithFraming(responsePromise, abortSignal,
|
208 | 209 | (response, initialContent) => {
|
209 |
| - const isGetRequest = requestMethod === 'get'; |
| 210 | + const isGetRequest = !fetchOptions?.method || fetchOptions.method === 'get'; |
210 | 211 | const isSuccessResponse = response.status >= 200 && response.status < 300;
|
211 | 212 |
|
212 | 213 | // For true 301/302/etc redirections to external URLs, we'll receive an opaque response
|
@@ -306,7 +307,7 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
|
306 | 307 | retryEnhancedNavAsFullPageLoad(internalDestinationHref);
|
307 | 308 | } else {
|
308 | 309 | // For non-get requests, we can't safely re-request, so just treat it as an error
|
309 |
| - replaceDocumentWithPlainText(`Error: ${requestMethod} request to ${internalDestinationHref} returned non-HTML content of type ${responseContentType || 'unspecified'}.`); |
| 310 | + replaceDocumentWithPlainText(`Error: ${fetchOptions.method} request to ${internalDestinationHref} returned non-HTML content of type ${responseContentType || 'unspecified'}.`); |
310 | 311 | }
|
311 | 312 | }
|
312 | 313 | },
|
|
0 commit comments