bogdanfinn / tls-client

net/http.Client like HTTP Client with options to select specific client TLS Fingerprints to use for requests.
BSD 4-Clause "Original" or "Old" License
670 stars 133 forks source link

Callback? #26

Open j9a12c20k opened 1 year ago

j9a12c20k commented 1 year ago

I am trying to use the client in nodejs and with the examples you set in cffi_dist/example_node/index_memory.js i am using exactly like this however instead of await i want to callback more functions rather then await which is causing bottleneck in the application. Is there a support for callback?

bogdanfinn commented 1 year ago

@j9a12c20k i do not really get what you are trying to achieve. Can you maybe provide some pseudo code like example of how you think it should look like / work at the end for you?

j9a12c20k commented 1 year ago

Hello,

My question is does awaiting for each request with TLS client create blocking? since i am noticing my app wait for all the first request to be finished first and then proceed forward with all request2, and then all 3. Is async await causing the issue or TLS? I am not sure if not can i use callback instead? I need each object to not wait for others and simply move forward to req2 and req3 once req1 is finished executing.


//Currently what I have right now.
class Request {
    constructor() {
        this.init()
    }
    async init() {
        await sendRequest1()
        await sendRequest2()
        await sendRequest3()
    }
    async sendRequest1() {
        //tls client send req
    }
    async sendRequest2() {
        //tls client send req
    }
    async sendRequest3() {
        //tls client send req
    }
}

//ex of callback

class Request {
    constructor() {
        this.init()
    }
    async init() {
        sendRequest1()
    }
    sendRequest1() {
        //tls client send req
        tlsclient.then(() => {
            sendRequest2()
        })
    }
    sendRequest2() {
        //tls client send req
        tlsclient.then(() => {
            sendRequest3()
        })
    }
    sendRequest3() {
        //tls client send req
        //finish up
    }
}
bogdanfinn commented 1 year ago

@j9a12c20k please take a look at this example and my comments i wrote about that.

const ffi = require('ffi-napi');

class TLS {
    constructor() {
        this.tls = this.initTLS();
    }

    // We load the shared library only once because we create only one instance of this class
    initTLS() {
        let tlsLib = "./../../tls-client/cffi_dist/dist/tls-client-darwin-amd64-1.3.5.dylib";
        return ffi.Library(tlsLib, {
            request: ["string", ["string"]],
            freeMemory: ["void", ['string']],
            getCookiesFromSession: ["string", ["string"]],
            addCookiesToSession: ['string', ['string']],
            destroyAll: ["string", []],
            destroySession: ["string", ["string"]],
        });
    }

    async request(payload, clientType = "chrome_105", followRedirects = true) {
        return new Promise((resolve, reject) => {
            const defaultPayload = {
                tlsClientIdentifier: clientType,
                followRedirects,
                insecureSkipVerify: false,
                withoutCookieJar: false,
                timeoutSeconds: 30,
                ...payload,
            };
            this.tls.request.async(JSON.stringify(defaultPayload), (error, resp) => {
                if (error) reject(error);
                const response = JSON.parse(resp);
                this.tls.freeMemory(response.id)
                resolve(response);
            });
        });
    }
}

class MyModule {
    // We use the instance of tlsClient as a constructor argument here to not load the shared library multiple times
    constructor(tlsClient, number) {
        this.number = number // just for demonstration
        this.tlsClient = tlsClient
    }

    async request1() {
        console.log(`do request 1 in module number ${this.number}`)
        return this.tlsClient.request({
            requestUrl: "https://tls.peet.ws/api/all"
        })
    }

    async request2() {
        console.log(`do request 2 in module number ${this.number}`)
        return this.tlsClient.request({
            requestUrl: "https://microsoft.com/"
        })
    }

    async request3() {
        console.log(`do request 3 in module number ${this.number}`)
        return this.tlsClient.request({
            requestUrl: "https://www.google.de/"
        })
    }

    async runModule() {
        // make sure that the requests inside the module are done synchronous.
        await this.request1()
        await this.request2()
        await this.request3()
    }
}

const main = () => {
    const tlsClientInstance = new TLS() // we only load the shared library once

    const myModule1 = new MyModule(tlsClientInstance, 1)
    const myModule2 = new MyModule(tlsClientInstance, 2)
    const myModule3 = new MyModule(tlsClientInstance, 3)

    // Important: Here we are not awaiting otherwise each module would only start if the previous one is done
    myModule1.runModule()
    myModule2.runModule()
    myModule3.runModule()
}

// run this example
main()

I'm not using the client myself in js. but afaik this should do what you want. Let me know if that helps you.

j9a12c20k commented 1 year ago

Hm, I tried doing it that way however it is still waiting for everything to do request1, it is really noticeable when i am doing > 25 at once