Spaces:
Runtime error
Runtime error
Download src/createClient.js from Kamciosz/librus-proxy-api: direct link, hf CLI and curl.
- Browser
- Download file 4.12 kB
-
https://huggingface.co/spaces/Kamciosz/librus-proxy-api/resolve/main/src/createClient.js
- Command line
-
hf download hf://spaces/Kamciosz/librus-proxy-api/src/createClient.js
-
curl -L -o createClient.js https://huggingface.co/spaces/Kamciosz/librus-proxy-api/resolve/main/src/createClient.js
4.12 kB
| /** | |
| * createClient.js | |
| * | |
| * Tworzy klienta HTTP opartego na 'got-scraping'. | |
| * Zast臋puje Axios, aby lepiej udawa膰 przegl膮dark臋 (TLS Fingerprinting). | |
| * To kluczowe, aby unikn膮膰 blokad IP/Bot贸w na Railway. | |
| */ | |
| import { gotScraping } from 'got-scraping'; | |
| import { CookieJar } from 'tough-cookie'; | |
| import { HttpsProxyAgent } from 'https-proxy-agent'; | |
| export function createClient() { | |
| const cookieJar = new CookieJar(); | |
| // Obs艂uga zewn臋trznego proxy (np. Residential Proxy) | |
| let agent = undefined; | |
| if (process.env.LIBRUS_PROXY_URL) { | |
| agent = { | |
| https: new HttpsProxyAgent(process.env.LIBRUS_PROXY_URL) | |
| }; | |
| } | |
| // Instancja got-scraping z automatycznym zarz膮dzaniem nag艂贸wkami i TLS | |
| const instance = gotScraping.extend({ | |
| cookieJar, | |
| timeout: { request: 60000 }, // 60s timeout | |
| retry: { limit: 2 }, | |
| agent, | |
| headers: { | |
| // Referer jest wymagany przez Librus | |
| "Referer": "https://portal.librus.pl/rodzina/synergia/loguj", | |
| }, | |
| // Konfiguracja generatora nag艂贸wk贸w (udajemy Chrome/Firefox na Desktopie) | |
| headerGeneratorOptions: { | |
| browsers: [ | |
| { name: 'chrome', minVersion: 110 }, | |
| { name: 'firefox', minVersion: 110 } | |
| ], | |
| devices: ['desktop'], | |
| locales: ['pl-PL', 'en-US'], | |
| operatingSystems: ['windows', 'linux'] | |
| } | |
| }); | |
| // Wrapper, kt贸ry udaje API Axios'a (get, post) dla kompatybilno艣ci z reszt膮 kodu | |
| const axiosLikeWrapper = { | |
| get: async (url, config = {}) => { | |
| const options = prepareOptions(config); | |
| try { | |
| const response = await instance.get(url, options); | |
| return formatResponse(response); | |
| } catch (error) { | |
| throw formatError(error); | |
| } | |
| }, | |
| post: async (url, data, config = {}) => { | |
| const options = prepareOptions(config); | |
| // Obs艂uga danych (URLSearchParams, JSON, string) | |
| if (data instanceof URLSearchParams) { | |
| options.body = data.toString(); | |
| if (!options.headers) options.headers = {}; | |
| options.headers['content-type'] = 'application/x-www-form-urlencoded'; | |
| } else if (typeof data === 'object' && data !== null) { | |
| options.json = data; | |
| } else { | |
| options.body = data; | |
| } | |
| try { | |
| const response = await instance.post(url, options); | |
| return formatResponse(response); | |
| } catch (error) { | |
| throw formatError(error); | |
| } | |
| } | |
| }; | |
| return axiosLikeWrapper; | |
| } | |
| // Pomocnicza funkcja do formatowania odpowiedzi jak w Axios | |
| function formatResponse(response) { | |
| let data = response.body; | |
| // Pr贸bujemy parsowa膰 JSON je艣li to string | |
| try { | |
| if (typeof data === 'string' && (data.trim().startsWith('{') || data.trim().startsWith('['))) { | |
| data = JSON.parse(data); | |
| } | |
| } catch (e) { /* ignore */ } | |
| return { | |
| data, | |
| status: response.statusCode, | |
| statusText: response.statusMessage, | |
| headers: response.headers, | |
| request: response.request | |
| }; | |
| } | |
| // Pomocnicza funkcja do formatowania b艂臋d贸w jak w Axios | |
| function formatError(error) { | |
| if (error.response) { | |
| error.response.data = error.response.body; | |
| try { | |
| if (typeof error.response.body === 'string') { | |
| error.response.data = JSON.parse(error.response.body); | |
| } | |
| } catch(e){} | |
| error.response.status = error.response.statusCode; | |
| } | |
| return error; | |
| } | |
| // Pomocnicza funkcja do mapowania opcji Axios -> Got | |
| function prepareOptions(config) { | |
| const options = { ...config }; | |
| // Mapowanie timeoutu (axios: timeout -> got: timeout.request) | |
| if (options.timeout && typeof options.timeout === 'number') { | |
| options.timeout = { request: options.timeout }; | |
| } | |
| return options; | |
| } | |