(
config: AxiosRequestConfig,
maxRedirects: number = 5,
agentOptions?: SecureRequestAgentOptions
)
| 154 | * @throws Error if any URL in the redirect chain is denied |
| 155 | */ |
| 156 | export async function secureAxiosRequest( |
| 157 | config: AxiosRequestConfig, |
| 158 | maxRedirects: number = 5, |
| 159 | agentOptions?: SecureRequestAgentOptions |
| 160 | ): Promise<AxiosResponse> { |
| 161 | let currentUrl = config.url |
| 162 | if (!currentUrl) { |
| 163 | throw new Error('secureAxiosRequest: url is required') |
| 164 | } |
| 165 | |
| 166 | let redirects = 0 |
| 167 | let currentConfig: AxiosRequestConfig = { |
| 168 | ...config, |
| 169 | maxRedirects: 0, |
| 170 | validateStatus: () => true, |
| 171 | httpsAgent: undefined, |
| 172 | httpAgent: undefined |
| 173 | } // Disable automatic redirects; agents set per-request below |
| 174 | |
| 175 | while (redirects <= maxRedirects) { |
| 176 | const target = await resolveAndValidate(currentUrl) |
| 177 | const agent = createPinnedAgent(target, agentOptions) |
| 178 | |
| 179 | currentConfig = { |
| 180 | ...currentConfig, |
| 181 | url: currentUrl, |
| 182 | ...(target.protocol === 'http' ? { httpAgent: agent } : { httpsAgent: agent }), |
| 183 | headers: { |
| 184 | ...currentConfig.headers, |
| 185 | Host: target.hostname |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | const response = await axios(currentConfig) |
| 190 | |
| 191 | // If it's a successful response (not a redirect), return it |
| 192 | if (response.status < 300 || response.status >= 400) { |
| 193 | return response |
| 194 | } |
| 195 | |
| 196 | // Handle redirect |
| 197 | const location = response.headers.location |
| 198 | if (!location) { |
| 199 | // No location header, but it's a redirect status - return the response |
| 200 | return response |
| 201 | } |
| 202 | |
| 203 | redirects++ |
| 204 | if (redirects > maxRedirects) { |
| 205 | throw new Error('Too many redirects') |
| 206 | } |
| 207 | |
| 208 | currentUrl = new URL(location, currentUrl).toString() |
| 209 | |
| 210 | // For redirects, we only need to preserve certain headers and change method if needed |
| 211 | if (response.status === 301 || response.status === 302 || response.status === 303) { |
| 212 | // For 303, or when redirecting POST requests, change to GET |
| 213 | if ( |
no test coverage detected