lentryd / NetSchoolApi

Асинхронный API-враппер для 'Сетевой Город. Образование' на Node.js.
https://lentryd.su/NetSchoolApi/
MIT License
25 stars 1 forks source link

Подключение через прокси #17

Open KOTOKOPOLb opened 1 week ago

KOTOKOPOLb commented 1 week ago

Можно ли как-то отправлять запросы сетевому городу через прокси? При запросах из вне России появляется ошибка 403 ( #6, #14 ) поэтому есть ли способ отправлять запросы через прокси из под Русского IP?

lentryd commented 1 week ago

Привет, у тебя есть личный прокси? Просто до этого пытались что-то подобное сделать через бесплатные прокси и система троллила подключения такого рода

KOTOKOPOLb commented 1 week ago

Пока нет. Хотел взять личный прокси, но пока не смог интегрировать даже бесплатный

lentryd commented 1 week ago

Можешь тогда попробовать сделать следующее, найди файл по адресу node_modules\@lentryd\web-client\dist\index.js и вставь туда этот код (заменив адрес прокси на свой )

"use strict";
const proxy = require('https-proxy-agent');
const agent = new proxy.HttpsProxyAgent(`http://<ip>:<port>`)
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Response = void 0;
const ws_1 = __importDefault(require("ws"));
const node_fetch_1 = __importStar(require("node-fetch"));
Object.defineProperty(exports, "Response", { enumerable: true, get: function () { return node_fetch_1.Response; } });
const cookie_1 = require("./cookie");
const url_1 = require("./url");
const headers_1 = require("./headers");
/**
 * Class for working with the site
 */
class Client {
    /**
     * Convert object to form data format
     * @param body source object
     * @param init request options
     * @returns request options with form data
     */
    static formData(body, init) {
        const data = [];
        for (let key in body)
            data.push(key + "=" + body[key]);
        return Object.assign(Object.assign({}, init), { body: encodeURI(data.join("&")), headers: Object.assign(Object.assign({}, init === null || init === void 0 ? void 0 : init.headers), { "Content-Type": "application/x-www-form-urlencoded" }) });
    }
    /**
     * Create a new instance of the Client class
     * @param origin Link to the site, for example http://example.com
     */
    constructor(origin) {
        this.origin = origin;
        // Work with cookies
        this._cookie = {};
        this.cookie = {
            get: () => {
                return (0, cookie_1.encodeCookie)(this._cookie);
            },
            set: (cookie) => {
                var _a;
                for (let { key, val } of (_a = (0, cookie_1.decodeCookie)(cookie)) !== null && _a !== void 0 ? _a : [])
                    this._cookie[key] = val;
                return this.cookie.get();
            },
        };
        // Work with headers
        this._headers = [];
        this.headers = {
            get: () => {
                return (0, headers_1.getHeaders)(this._headers);
            },
            set: (key, value) => {
                this._headers = (0, headers_1.setHeaders)(this._headers, key, value);
                return this.headers.get();
            },
            del: (key) => {
                this._headers = (0, headers_1.delHeaders)(this._headers, key);
                return this.headers.get();
            },
        };
        // Work with main path
        this._path = "/";
        this.path = {
            get: () => {
                return this._path;
            },
            set: (path) => {
                if ((0, url_1.isAbsolute)(path))
                    throw new Error("path must be relative to origin");
                this._path = path;
                return this.path.get();
            },
        };
        // Response hooks
        this._responseHook = () => __awaiter(this, void 0, void 0, function* () { return void 0; });
        // Check the origin for correctness
        if (!(0, url_1.isAbsolute)(origin))
            throw new Error("origin must be an absolute path");
        // Set the origin in the headers
        this.origin = new URL(origin).origin;
        this.headers.set("Origin", this.origin);
        this.headers.set("Referer", this.origin);
        this.headers.set("Cookie", () => this.cookie.get());
    }
    onResponse(hook) {
        this._responseHook = hook;
    }
    /**
     * Join the path to the origin
     * @param paths Path to the required resource
     * @returns Full path to the resource
     */
    join(...paths) {
        return (0, url_1.joinURL)(this.origin, this.path.get(), ...paths);
    }
    ws(url, init) {
        if (!(0, url_1.isAbsolute)(url))
            url = this.join(url);
        if (init === null || init === void 0 ? void 0 : init.params)
            url += (0, url_1.encodeQuery)(init.params);
        return new ws_1.default(url.replace("http", "ws"), Object.assign(Object.assign({}, init), { headers: Object.assign(Object.assign({}, init === null || init === void 0 ? void 0 : init.headers), this.headers.get()) }));
    }
    /**
     * Method for make request to the site
     * @param url relative path to the resource
     * @param init request options
     * @returns response
     */
    request(url, init) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a;
            // If the path is not absolute, then add the origin to it
            if (!(0, url_1.isAbsolute)(url))
                url = this.join(url);
            // If there are parameters, then add them to the path
            if (init === null || init === void 0 ? void 0 : init.params)
                url += (0, url_1.encodeQuery)(init.params);
            // Make a request
            let res = yield (0, node_fetch_1.default)(url, Object.assign(Object.assign({agent}, init), { headers: Object.assign(Object.assign({}, this.headers.get()), init === null || init === void 0 ? void 0 : init.headers) }));
            // Run response hook
            const hook = yield this._responseHook(res, url, init);
            // If the hook returns a response, then save it
            if (hook instanceof node_fetch_1.Response)
                res = hook;
            // If the request was unsuccessful, then throw an error
            if (!res.ok) {
                throw new Error("Fetch failed.\n\t- url: " + url + "\n\t- status: " + res.status);
            }
            // Save cookies (if any)
            this.cookie.set((_a = res.headers.raw()) === null || _a === void 0 ? void 0 : _a["set-cookie"]);
            // Return the response
            return res;
        });
    }
    /**
     * Get request
     * @param url relative path to the resource
     * @param init request options
     * @returns response
     */
    get(url, init) {
        // Make a request with the GET method
        return this.request(url, Object.assign(Object.assign({}, init), { method: "get" }));
    }
    /**
     * Post request
     * @param url relative path to the resource
     * @param init request options
     * @returns response
     */
    post(url, init) {
        // Make a request with the POST method
        return this.request(url, Object.assign(Object.assign({}, init), { method: "post" }));
    }
}
exports.default = Client;
//# sourceMappingURL=index.js.map

так же в терминале выполни команду npm install https-proxy-agent и потом можешь запускать свой код

lentryd commented 1 week ago

Если появляются ошибки 4xx (хотя до этого их не было), то скорее всего это тебя не пускает защита сетевого. Ну, а если вдруг у тебя получится найти прокси который будет работать нормально, то добавлю такой функционал в либу

lentryd commented 1 week ago

@KOTOKOPOLb, есть новости касательно прокси?

KOTOKOPOLb commented 1 week ago

@lentryd, пока нет. Не могу найти нормальны, полностью рабочий прокси, думаю пока попробовать создать свой и если всё будет работать - попробовать арендовать прокси

KOTOKOPOLb commented 1 week ago

@lentryd, подключение через прокси работает. Как вариант не искать рабочий бесплатный прокси, а добавить функцию\параметр, через который пользователь может указать свой прокси (который он нашёл или купил). Попробовал поставить прокси на Германском сервере и подключение идёт, но как и ожидалось - сетевой блокирует подключение. image Сейчас думаю попробовать добавить возможность подключения через Socks.

lentryd commented 1 week ago

подключение через прокси работает.

Ну да, запросы отправляться будут, в этом сомнений не было)

Попробовал поставить прокси на Германском сервере и подключение идёт, но как и ожидалось - сетевой блокирует подключение.

Ожидаемо, она даже прокси с русским ip не всегда пропускает.

В #6 как раз пытались сделать возможность хостить приложение на зарубежных серверах и пытались использовать бесплатные прокси с российскими ip, но система не пропускала и решили забить на это. Может тебе проще захостить на каком-нибудь российской vps?

KOTOKOPOLb commented 1 week ago

Может тебе проще захостить на каком-нибудь российской vps?

Не знаю, лично мне удобнее через прокси, тк российский vds\vps будет выходить дороже. На счёт добавления возможность указать прокси - думаю будут ещё люди с такой же нуждой, в виде прокси.

KOTOKOPOLb commented 1 week ago

На счёт бесплатного прокси - сделал мини скрипт, который парсит списки с прокси и проверяет их. На 500 находится ~15 рабочих, но некоторые не подключаются к google.com, некоторое к ya.ru и ни один пока не смог подключиться к сайту сго

lentryd commented 1 week ago

На счёт добавления возможность указать прокси - думаю будут ещё люди с такой же нуждой, в виде прокси.

Окей, тогда на днях постараюсь добавить такую возможность