( req: ProxyRequest, accessToken: string | null, requestId: string )
| 129 | } |
| 130 | |
| 131 | async function fetchCsrf( |
| 132 | req: ProxyRequest, |
| 133 | accessToken: string | null, |
| 134 | requestId: string |
| 135 | ): Promise<CsrfBundle | null> { |
| 136 | const url = buildOdataUrl(req, '/$metadata') |
| 137 | const response = await secureFetchWithValidation( |
| 138 | url, |
| 139 | { |
| 140 | method: 'GET', |
| 141 | headers: { |
| 142 | Authorization: buildAuthHeader(req, accessToken), |
| 143 | Accept: 'application/xml', |
| 144 | 'X-CSRF-Token': 'Fetch', |
| 145 | }, |
| 146 | timeout: OUTBOUND_FETCH_TIMEOUT_MS, |
| 147 | }, |
| 148 | 'baseUrl' |
| 149 | ) |
| 150 | |
| 151 | if (!response.ok) { |
| 152 | const text = await response.text().catch(() => '') |
| 153 | logger.warn(`[${requestId}] CSRF fetch failed (${response.status}): ${text}`) |
| 154 | return null |
| 155 | } |
| 156 | |
| 157 | const token = response.headers.get('x-csrf-token') |
| 158 | const cookie = joinSetCookies(response) |
| 159 | if (!token) return null |
| 160 | return { token, cookie } |
| 161 | } |
| 162 | |
| 163 | function resolveHost(req: ProxyRequest): string { |
| 164 | if (req.deploymentType === 'cloud_public') { |
no test coverage detected