1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
const SUPPORTED_METHODS = ['patch', 'post', 'put'];
function needsCaptchaResponse(err) {
return (
SUPPORTED_METHODS.includes(err?.config?.method) && err?.response?.data?.needs_captcha_response
);
}
const showCaptchaModalAndResubmit = async (axios, data, errConfig) => {
// NOTE: We asynchronously import and unbox the module. Since this is included globally, we don't
// do a regular import because that would increase the size of the webpack bundle.
const { waitForCaptchaToBeSolved } = await import('~/captcha/wait_for_captcha_to_be_solved');
// show the CAPTCHA modal and wait for it to be solved or closed
const captchaResponse = await waitForCaptchaToBeSolved(data.captcha_site_key);
// resubmit the original request with the captcha_response and spam_log_id in the headers
const originalData = JSON.parse(errConfig.data);
const originalHeaders = errConfig.headers;
return axios({
method: errConfig.method,
url: errConfig.url,
headers: {
...originalHeaders,
'X-GitLab-Captcha-Response': captchaResponse,
'X-GitLab-Spam-Log-Id': data.spam_log_id,
},
data: originalData,
});
};
export function registerCaptchaModalInterceptor(axios) {
return axios.interceptors.response.use(
(response) => {
return response;
},
(err) => {
if (needsCaptchaResponse(err)) {
return showCaptchaModalAndResubmit(axios, err.response.data, err.config);
}
return Promise.reject(err);
},
);
}
|