| 92 | } |
| 93 | |
| 94 | export function xsrfInterceptorFn( |
| 95 | req: HttpRequest<unknown>, |
| 96 | next: HttpHandlerFn, |
| 97 | ): Observable<HttpEvent<unknown>> { |
| 98 | // Skip both non-mutating requests |
| 99 | // Non-mutating requests generally don't require a token. |
| 100 | if (!inject(XSRF_ENABLED) || req.method === 'GET' || req.method === 'HEAD') { |
| 101 | return next(req); |
| 102 | } |
| 103 | |
| 104 | try { |
| 105 | const locationHref = inject(PlatformLocation).href; |
| 106 | const {origin: locationOrigin} = new URL(locationHref); |
| 107 | // We can use `new URL` to normalize a relative URL like '//something.com' to |
| 108 | // 'https://something.com' in order to make consistent same-origin comparisons. |
| 109 | const {origin: requestOrigin} = new URL(req.url, locationOrigin); |
| 110 | |
| 111 | if (locationOrigin !== requestOrigin) { |
| 112 | return next(req); |
| 113 | } |
| 114 | } catch { |
| 115 | // Handle invalid URLs gracefully. |
| 116 | return next(req); |
| 117 | } |
| 118 | |
| 119 | const token = inject(HttpXsrfTokenExtractor).getToken(); |
| 120 | const headerName = inject(XSRF_HEADER_NAME); |
| 121 | |
| 122 | // Be careful not to overwrite an existing header of the same name. |
| 123 | if (token != null && !req.headers.has(headerName)) { |
| 124 | req = req.clone({headers: req.headers.set(headerName, token)}); |
| 125 | } |
| 126 | return next(req); |
| 127 | } |
| 128 | |
| 129 | /** |
| 130 | * `HttpInterceptor` which adds an XSRF token to eligible outgoing requests. |