vadimpronin / guacamole-lite

Node.js library for creating Guacamole-compatible servers. Guacamole is a RDP/VNC/SSH/Telnet client for HTML5 browsers.
Apache License 2.0
250 stars 78 forks source link

Server processConnectionSettings callback #2

Closed fredericosilva closed 7 years ago

fredericosilva commented 7 years ago

Hello,

What is your use case for this callback?

Will you be open for a PR to make callbacks async?

Thank you

vadimpronin commented 7 years ago

Hi! I use this callback to authorise client and change/manipulate with connection parameters. Like in this example:

const callbacks = {
    processConnectionSettings: function (settings) {
        if (settings.expiration < Date.now()) {
            console.error('Token expired');

            throw 'Token expired';
        }

        settings.connection['recording-path'] = '/data/recordings/' + settings.s3.bucket;
        settings.connection['drive-path'] = '/tmp/guacamole_' + settings.vmId;

        return settings;
    }
};

So for my purposes it must stay sync. But you are more than welcome to make a PR with another callback (or another set of callbacks) which will be async.

fredericosilva commented 7 years ago

Don't you think it will be more generic to force all callback to be async?

Your example would be something like:

const callbacks = {
    processConnectionSettings: function (settings, callback) {
        if (settings.expiration < Date.now()) {
            console.error('Token expired');

            return callback(new Error('Token expired'));
        }

        settings.connection['recording-path'] = '/data/recordings/' + settings.s3.bucket;
        settings.connection['drive-path'] = '/tmp/guacamole_' + settings.vmId;

        callback(undefined, settings);
    }
};
vadimpronin commented 7 years ago

Seems ok to me. But I don't see how is it async now?

server.callbacks.processConnectionSettings(this.connectionSettings, (err, settings) => {

looks pretty synchronous to me. Or am I missing something?

fredericosilva commented 7 years ago

On your example is sill sync on an async fashion. On my use case I need to do a http request to get all the information for the connection.

processConnectionSettings: (settings, callback) => {
    request
        .get(`http://example.com/vm/${settings.connection.vm}`)
        .end((err, rsp) => {
            if (err) { return callback(err); }

            settings.connection.hostname = rsp.body.hostname

            callback(err, settings);
        });
}
vadimpronin commented 7 years ago

I see. Seems fine. The only thing that concerns me is err as the first parameter of the callback. Because returning undefined in case when there's no error doesn't seem neat to me. I'm talking about this:

callback(undefined, settings);

What do you think we we'll be throwing errors and returning just settings?

fredericosilva commented 7 years ago

One can't catch threw errors from a async function, it's a good practice to use first argument for errors, all node core function use this. Undefined or null is a matter of personal taste I would say.

We could also use async/await or more "pure" promises to handle such behavior.

vadimpronin commented 7 years ago

Ok, then. I'm merging the PR :)

vadimpronin commented 7 years ago

By the way, I know it's not clear as there is no documentation, but there's no need to make another request to backend to get connection parameters. You can all the parameters when you are opening connection to guacamole-lite server in encrypted token.

I'm writing docs now to make it more clear :)

vadimpronin commented 7 years ago

UPD: I've updated readme.md to have some examples. I hope they are clear enough and show what functionality is implemented in guacamole-lite at the moment

fredericosilva commented 7 years ago

Thanks for the documentation and the example :)