| function proxyRequest({ url, proxy, method = 'GET', body = null, headers = {}, cookies = [], sessionHeaders = {} }) { |
| return new Promise(async (resolve, reject) => { |
| if (!url) return reject("Missing url parameter"); |
| |
| const context = await global.browser |
| .createBrowserContext({ |
| proxyServer: proxy ? `http://${proxy.host}:${proxy.port}` : undefined, |
| }) |
| .catch(() => null); |
| |
| if (!context) return reject("Failed to create browser context"); |
|
|
| let isResolved = false; |
|
|
| var cl = setTimeout(async () => { |
| if (!isResolved) { |
| await context.close(); |
| reject("Timeout Error"); |
| } |
| }, global.timeOut || 60000); |
|
|
| try { |
| const page = await context.newPage(); |
|
|
| if (proxy?.username && proxy?.password) |
| await page.authenticate({ |
| username: proxy.username, |
| password: proxy.password, |
| }); |
|
|
| const targetUrl = new URL(url); |
| |
| if (cookies && cookies.length > 0) { |
| const cookiesToSet = cookies.map(cookie => ({ |
| name: cookie.name, |
| value: cookie.value, |
| domain: cookie.domain || targetUrl.hostname, |
| path: cookie.path || '/', |
| secure: cookie.secure !== undefined ? cookie.secure : targetUrl.protocol === 'https:', |
| httpOnly: cookie.httpOnly || false, |
| sameSite: cookie.sameSite || 'Lax' |
| })); |
| await page.setCookie(...cookiesToSet); |
| } |
|
|
| if (sessionHeaders && sessionHeaders['user-agent']) { |
| await page.setUserAgent(sessionHeaders['user-agent']); |
| } |
|
|
| const sanitizedHeaders = { ...headers }; |
| const headersToRemove = ['host', 'content-length', 'connection', 'accept-encoding', 'transfer-encoding']; |
| headersToRemove.forEach(h => { |
| delete sanitizedHeaders[h]; |
| delete sanitizedHeaders[h.toLowerCase()]; |
| }); |
|
|
| if (sessionHeaders) { |
| if (sessionHeaders['accept-language'] && !sanitizedHeaders['accept-language']) { |
| sanitizedHeaders['accept-language'] = sessionHeaders['accept-language']; |
| } |
| } |
|
|
| await page.goto(targetUrl.origin, { waitUntil: 'domcontentloaded', timeout: 30000 }).catch(() => {}); |
|
|
| const result = await page.evaluate(async (options) => { |
| try { |
| const fetchOptions = { |
| method: options.method, |
| headers: options.headers || {}, |
| credentials: 'include' |
| }; |
|
|
| if (options.body && ['POST', 'PUT', 'PATCH'].includes(options.method.toUpperCase())) { |
| fetchOptions.body = typeof options.body === 'string' |
| ? options.body |
| : JSON.stringify(options.body); |
| if (typeof options.body === 'object' && !fetchOptions.headers['content-type']) { |
| fetchOptions.headers['content-type'] = 'application/json'; |
| } |
| } |
|
|
| const response = await fetch(options.url, fetchOptions); |
| |
| const responseHeaders = {}; |
| response.headers.forEach((value, key) => { |
| responseHeaders[key] = value; |
| }); |
|
|
| let responseBody; |
| const contentType = response.headers.get('content-type') || ''; |
| |
| if (contentType.includes('application/json')) { |
| responseBody = await response.json(); |
| } else { |
| responseBody = await response.text(); |
| } |
|
|
| return { |
| status: response.status, |
| statusText: response.statusText, |
| headers: responseHeaders, |
| body: responseBody, |
| ok: response.ok |
| }; |
| } catch (e) { |
| return { error: e.message }; |
| } |
| }, { url, method, body, headers: sanitizedHeaders }); |
|
|
| if (result.error) { |
| await context.close(); |
| isResolved = true; |
| clearTimeout(cl); |
| return reject(result.error); |
| } |
|
|
| const updatedCookies = await page.cookies(); |
| |
| const browserHeaders = await page.evaluate(() => { |
| return { |
| 'user-agent': navigator.userAgent, |
| 'accept-language': navigator.language || navigator.languages.join(',') |
| }; |
| }); |
|
|
| await context.close(); |
| isResolved = true; |
| clearInterval(cl); |
|
|
| resolve({ |
| response: result, |
| cookies: updatedCookies, |
| browserHeaders |
| }); |
|
|
| } catch (e) { |
| if (!isResolved) { |
| await context.close(); |
| clearTimeout(cl); |
| reject(e.message); |
| } |
| } |
| }); |
| } |
|
|
| module.exports = proxyRequest; |
|
|